import json
import logging
import sqlite3
import threading
import time
from datetime import timedelta
from pathlib import Path

from accounts.models import FeatureSwitch
from codes.models import Code
from django.conf import settings
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.core.paginator import Paginator
from django.db.models import Q
from django.http import HttpResponse, JsonResponse
from django.shortcuts import get_object_or_404, redirect, render
from django.utils import timezone
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_GET, require_POST

from .code_executor import CodeExecutor
from .models import Battle, BattleStatistics, MatchQueue, WorldCup, WorldCupParticipant, WorldCupMatch
from django.db.models import Sum, Count, F
from .node_server_manager import get_node_server_manager

# 获取日志记录器
logger = logging.getLogger(__name__)


def check_battle_creation_enabled(request):
    """检查对战创建功能是否启用"""
    if not FeatureSwitch.is_feature_enabled('battle_creation'):
        disabled_message = FeatureSwitch.get_disabled_message('battle_creation')
        if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
            return JsonResponse({'success': False, 'error': disabled_message}, status=403)
        else:
            messages.error(request, disabled_message)
            return redirect('home')
    return None


@login_required
def battle_list(request):
    """显示用户的对战列表"""
    # 获取用户参与的所有对战
    battles = Battle.objects.filter(Q(player1=request.user) | Q(player2=request.user)).order_by('-created_at')

    # 计算胜负统计（排除练习赛中自己打自己的情况）
    finished_battles = battles.filter(status='finished')

    # 统计胜负（排除自己打自己的情况）
    win_count = 0
    lose_count = 0

    for battle in finished_battles:
        # 自己打自己不计入统计
        if battle.player1 == battle.player2:
            continue

        if battle.result == 'player1_win' and battle.player1 == request.user:
            win_count += 1
        elif battle.result == 'player2_win' and battle.player2 == request.user:
            win_count += 1
        elif battle.result == 'player1_win' and battle.player2 == request.user:
            lose_count += 1
        elif battle.result == 'player2_win' and battle.player1 == request.user:
            lose_count += 1

    # 计算胜率
    total_counted_battles = win_count + lose_count
    win_rate = (win_count / total_counted_battles * 100) if total_counted_battles > 0 else 0

    # 分页处理
    paginator = Paginator(battles, 10)  # 每页显示10条
    page_number = request.GET.get('page')
    page_obj = paginator.get_page(page_number)

    return render(
        request,
        'battles/battle_list.html',
        {
            'page_obj': page_obj,
            'win_count': win_count,
            'lose_count': lose_count,
            'win_rate': round(win_rate, 1),
            'battle_creation_enabled': FeatureSwitch.is_feature_enabled('battle_creation'),
        },
    )


@login_required
def battle_detail(request, battle_id):
    """显示对战详情"""
    battle = get_object_or_404(Battle, id=battle_id)

    # 检查用户是否有权限查看此对战
    if not battle.is_public and request.user != battle.player1 and request.user != battle.player2 and not request.user.is_staff:
        messages.error(request, '您没有权限查看此对战记录。')
        return redirect('battles:battle_list')

    # 只获取回合数量，不加载具体数据
    rounds_count = battle.rounds.count()

    # 准备基本的 battle 数据，不包含大数据量的 rounds 信息
    battle_data = {
        'id': battle.id,
        'player1': {
            'username': battle.player1.username,
        },
        'player2': {
            'username': battle.player2.username,
        },
        'player1_code': {
            'language': battle.player1_code.language,
        },
        'player2_code': {
            'language': battle.player2_code.language,
        },
        'game_config': battle.game_config,
        'map_config': battle.map_config,
        'init_command': battle.init_command,
        'end_command': battle.end_command,
        'rounds_count': rounds_count,
    }

    return render(
        request,
        'battles/battle_detail.html',
        {
            'battle': battle,
            'battle_data': battle_data,
            'rounds_count': rounds_count,
        },
    )


@login_required
def battle_error(request, battle_id):
    """显示战斗错误详情页面"""
    battle = get_object_or_404(Battle, id=battle_id)

    # 检查用户是否有权限查看此对战
    if not battle.is_public and request.user != battle.player1 and request.user != battle.player2 and not request.user.is_staff:
        messages.error(request, '您没有权限查看此对战记录。')
        return redirect('battles:battle_list')

    # 只允许查看错误状态的战斗
    if battle.status != 'error':
        return redirect('battles:battle_detail', battle_id=battle_id)

    return render(
        request,
        'battles/battle_error.html',
        {
            'battle': battle,
        },
    )


@login_required
def battle_create(request):
    """创建新对战"""
    # 检查用户是否为管理员，如果是则拒绝访问
    if request.user.is_staff:
        messages.error(request, '管理员账号不能创建对战。')
        return redirect('battles:battle_list')

    # 检查对战创建功能是否启用
    feature_check_result = check_battle_creation_enabled(request)
    if feature_check_result:
        return feature_check_result

    if request.method == 'POST':
        try:
            code_id = request.POST.get('code_id')
            battle_type_input = request.POST.get('battle_type_input', 'random')
            round_limit = int(request.POST.get('round_limit', 200))  # 从前端获取回合数限制，默认200
            time_limit = int(request.POST.get('time_limit', 30))
            is_public = True  # 默认为公开
            save_round_inputs = request.POST.get('save_round_inputs') == 'on'  # 复选框选中时为'on'
            map_selection = request.POST.get('map_selection', settings.BATTLE_ENGINE.get('DEFAULT_MAP', 'main6'))  # 获取选择的地图

            code = get_object_or_404(Code, id=code_id, user=request.user)

            # 检查用户是否已经在匹配队列中
            existing_queue = MatchQueue.objects.filter(user=request.user, status='waiting').first()

            if existing_queue:
                messages.warning(request, '您已经在匹配队列中，请等待匹配完成或取消当前匹配。')
                return redirect('battles:match_status')

            if battle_type_input == 'random':
                # 随机匹配逻辑
                return handle_random_match(request, code, round_limit, time_limit, is_public, save_round_inputs, map_selection)

            elif battle_type_input == 'practice':
                # 练习赛逻辑
                opponent_code_id = request.POST.get('opponent_code_id')
                if not opponent_code_id:
                    messages.error(request, '请选择对手代码。')
                    return redirect('battles:battle_create')
                return handle_practice_match(request, code, opponent_code_id, round_limit, time_limit, is_public, save_round_inputs, map_selection)

        except Exception as e:
            messages.error(request, f'创建对战失败: {str(e)}')
            return redirect('battles:battle_create')

    # 获取用户的代码列表
    codes = Code.objects.filter(user=request.user, is_active=True)

    # 获取当前匹配状态
    current_match = MatchQueue.objects.filter(user=request.user, status='waiting').first()

    # 获取练习赛可用的对手代码
    # 1. 用户自己的其他代码
    user_other_codes = Code.objects.filter(user=request.user, is_active=True)

    # 2. 其他非管理员用户的可挑战代码
    # 星标代码默认可挑战，功能开关控制所有私有代码（包括非星标私有代码）
    if FeatureSwitch.is_feature_enabled('private_code_challenge'):
        # 如果启用私有代码挑战，包含公开代码、星标代码和所有私有代码
        public_codes = Code.objects.filter(
            Q(is_public=True) | Q(is_starred=True) | Q(is_public=False),
            is_active=True,
            user__is_staff=False
        ).exclude(user=request.user).select_related('user')
    else:
        # 如果禁用私有代码挑战，包含公开代码和星标代码（星标代码默认可挑战）
        public_codes = Code.objects.filter(
            Q(is_public=True) | Q(is_starred=True),
            is_active=True,
            user__is_staff=False
        ).exclude(user=request.user).select_related('user')

    # 获取队列状态
    from .battle_queue_manager import get_manual_battle_queue_manager
    queue_manager = get_manual_battle_queue_manager()
    queue_status = queue_manager.get_queue_status()

    return render(
        request,
        'battles/battle_create.html',
        {
            'codes': codes,
            'current_match': current_match,
            'user_other_codes': user_other_codes,
            'public_codes': public_codes,
            'queue_status': queue_status,
        },
    )


@login_required
def battle_statistics(request):
    """显示用户的对战统计"""
    # 获取或创建用户的对战统计
    stats, created = BattleStatistics.objects.get_or_create(user=request.user)

    # 获取最近的对战记录（排除已取消的对战）
    recent_battles = (
        Battle.objects.filter(Q(player1=request.user) | Q(player2=request.user))
        .exclude(status='cancelled')
        .order_by('-created_at')[:5]
    )

    return render(
        request,
        'battles/battle_statistics.html',
        {
            'stats': stats,
            'recent_battles': recent_battles,
            'win_rate': stats.get_win_rate(),
            'kd_ratio': stats.get_kd_ratio(),
            'detailed_stats': stats.get_detailed_stats(),
        },
    )


@login_required
def battle_ranking(request):
    """显示对战排行榜（排除世界杯对战和管理员账号）"""
    from django.contrib.auth.models import User
    from django.core.paginator import Paginator

    # 获取所有非管理员用户，并为每个用户创建或获取统计数据
    all_users = User.objects.filter(is_staff=False).order_by('id')
    user_stats_list = []

    for user in all_users:
        try:
            stats = BattleStatistics.objects.get(user=user)
        except BattleStatistics.DoesNotExist:
            # 为没有统计记录的用户创建默认统计对象（不保存到数据库）
            stats = BattleStatistics(
                user=user,
                total_battles=0,
                wins=0,
                losses=0,
                draws=0,
                total_score=0,
                average_score=0.0,
                best_score=0,
                rating=0,
                current_rank=0,
                highest_rank=0,
            )
        user_stats_list.append(stats)

    # 修改排序逻辑：先按是否参与过战斗排序，未参与战斗的排在最后
    # 然后按优先级排序：胜场数 > 平局数 > 负场数(越少越好) > 评分
    all_stats = sorted(user_stats_list, key=lambda x: (
        x.total_battles == 0,  # 未参与战斗的排在最后（True > False）
        -x.wins,               # 胜场数降序
        -x.draws,              # 平局数降序
        x.losses,              # 负场数升序（越少越好）
        -x.rating              # 评分降序
    ))

    # 分页设置
    paginator = Paginator(all_stats, 10)  # 每页显示10条记录
    page_number = request.GET.get('page')
    top_stats = paginator.get_page(page_number)

    # 获取当前用户的排名和统计（仅对非管理员用户显示）
    user_stats = None
    user_rank = None
    user_kd_ratio = 0.0
    user_detailed_stats = None

    # 如果当前用户不是管理员，显示其排名信息
    if not request.user.is_staff:
        for i, stats in enumerate(all_stats):
            if stats.user == request.user:
                user_stats = stats
                user_rank = i + 1
                if hasattr(stats, 'get_kd_ratio'):
                    user_kd_ratio = stats.get_kd_ratio()
                if hasattr(stats, 'get_detailed_stats'):
                    user_detailed_stats = stats.get_detailed_stats()
                break

    return render(
        request,
        'battles/battle_ranking.html',
        {
            'top_stats': top_stats,
            'user_stats': user_stats,
            'user_rank': user_rank,
            'user_kd_ratio': user_kd_ratio,
            'user_detailed_stats': user_detailed_stats,
            'paginator': paginator,
            'page_obj': top_stats,
        },
    )


@login_required
def battles_history(request):
    """显示所有对战历史记录（排除世界杯对战）"""
    # 获取所有公开的对战记录，排除世界杯对战
    battles = Battle.objects.filter(is_public=True).exclude(battle_type__in=['worldcup_regular', 'worldcup_championship'])

    # 获取筛选参数
    search_query = request.GET.get('search', '').strip()
    battle_id_filter = request.GET.get('battle_id', '').strip()
    status_filter = request.GET.get('status', '')
    battle_type_filter = request.GET.get('battle_type', '')
    date_from = request.GET.get('date_from', '')
    date_to = request.GET.get('date_to', '')
    exciting_only = request.GET.get('exciting_only', '') in ['on', '1', 'true']  # 修正：精彩战斗筛选

    # 应用筛选
    if search_query:
        battles = battles.filter(Q(player1__username__icontains=search_query) | Q(player2__username__icontains=search_query))

    if battle_id_filter:
        battles = battles.filter(id=battle_id_filter)

    if status_filter:
        battles = battles.filter(status=status_filter)

    if battle_type_filter:
        battles = battles.filter(battle_type=battle_type_filter)

    if date_from:
        battles = battles.filter(created_at__date__gte=date_from)

    if date_to:
        battles = battles.filter(created_at__date__lte=date_to)

    # 新增：精彩战斗筛选
    if exciting_only:
        battles = battles.filter(is_exciting=True).order_by('-excitement_score', '-created_at')
    else:
        battles = battles.order_by('-created_at')

    # 计算统计数据（基于筛选后的对战数据）
    total_battles = battles.count()
    finished_battles = battles.filter(status='finished').count()
    running_battles = battles.filter(status='running').count()
    pending_battles = battles.filter(status='pending').count()
    error_battles = battles.filter(status='error').count()
    exciting_battles = battles.filter(is_exciting=True).count()  # 新增：精彩战斗统计

    # 分页处理
    paginator = Paginator(battles, 10)  # 每页显示10条
    page_number = request.GET.get('page')
    page_obj = paginator.get_page(page_number)

    # 准备选择项
    from .models import BATTLE_STATUS_CHOICES, BATTLE_TYPE_CHOICES

    battle_status_choices = BATTLE_STATUS_CHOICES
    battle_type_choices = BATTLE_TYPE_CHOICES

    return render(
        request,
        'battles/battles_history.html',
        {
            'page_obj': page_obj,
            'search_query': search_query,
            'battle_id_filter': battle_id_filter,
            'status_filter': status_filter,
            'battle_type_filter': battle_type_filter,
            'date_from': date_from,
            'date_to': date_to,
            'exciting_only': exciting_only,  # 新增
            'total_battles': total_battles,
            'finished_battles': finished_battles,
            'running_battles': running_battles,
            'pending_battles': pending_battles,
            'error_battles': error_battles,
            'exciting_battles': exciting_battles,  # 新增
            'battle_status_choices': battle_status_choices,
            'battle_type_choices': battle_type_choices,
        },
    )


# API接口
@csrf_exempt
@require_POST
@login_required
def api_battle_create(request):
    """API: 创建对战"""
    # 检查对战创建功能是否启用
    feature_check_result = check_battle_creation_enabled(request)
    if feature_check_result:
        return feature_check_result

    try:
        data = json.loads(request.body)
        code_id = data.get('code_id')
        battle_type_input = data.get('battle_type_input', 'random')
        round_limit = int(data.get('round_limit', 100))
        time_limit = int(data.get('time_limit', 30))
        friend_username = data.get('friend_username', '').strip()

        # 验证代码
        code = get_object_or_404(Code, id=code_id, user=request.user)

        # 检查用户是否已经在匹配队列中
        existing_queue = MatchQueue.objects.filter(user=request.user, status='waiting').first()
        if existing_queue:
            return JsonResponse({'success': False, 'message': '您已经在匹配队列中，请等待匹配完成或取消当前匹配'})

        # 根据对战类型处理
        if battle_type_input == 'random':
            # 随机匹配逻辑
            response = handle_random_match(request, code, round_limit, time_limit)
            if hasattr(response, 'url') and 'battle_detail' in response.url:
                return JsonResponse({'status': 'success', 'message': '随机匹配成功', 'redirect_url': response.url})
            else:
                return JsonResponse({'error': '随机匹配失败'}, status=400)
        else:
            return JsonResponse({'error': '无效的对战模式'}, status=400)

    except Exception as e:
        logger.error(f'API创建对战失败: {str(e)}')
        return JsonResponse({'error': str(e)}, status=400)


@require_GET
@login_required
def api_battle_status(request, battle_id):
    """API: 获取对战状态"""
    try:
        battle = get_object_or_404(Battle, id=battle_id)

        # 检查用户是否有权限查看此对战
        if (
            not battle.is_public
            and request.user != battle.player1
            and request.user != battle.player2
            and not request.user.is_staff
        ):
            return JsonResponse({'error': '没有权限'}, status=403)

        # 返回对战状态
        return JsonResponse(
            {
                'status': battle.status,
                'result': battle.result,
                'total_rounds': battle.total_rounds,
                'player1_score': battle.player1_score,
                'player2_score': battle.player2_score,
                'created_at': battle.created_at.isoformat(),
                'started_at': battle.started_at.isoformat() if battle.started_at else None,
                'finished_at': battle.finished_at.isoformat() if battle.finished_at else None,
            }
        )
    except Exception as e:
        logger.error(f'获取对战状态失败: {str(e)}')
        return JsonResponse({'error': str(e)}, status=400)


@require_GET
@login_required
def api_battle_round_progress(request, battle_id):
    """API: 获取战斗回合进度"""
    try:
        battle = get_object_or_404(Battle, id=battle_id)

        # 检查用户是否有权限查看此对战
        if (
            not battle.is_public
            and request.user != battle.player1
            and request.user != battle.player2
            and not request.user.is_staff
        ):
            return JsonResponse({'error': '没有权限'}, status=403)

        # 获取当前回合数（已完成的回合数）
        current_round = battle.rounds.count()
        total_rounds = battle.total_rounds or 0

        # 返回回合进度数据
        return JsonResponse(
            {
                'current_round': current_round,
                'total_rounds': total_rounds,
                'status': battle.status,
                'progress_percent': (current_round / total_rounds * 100) if total_rounds > 0 else 0,
                'battle_id': battle.id,
            }
        )
    except Exception as e:
        logger.error(f'获取战斗回合进度失败: {str(e)}')
        return JsonResponse({'error': str(e)}, status=400)








# 代码执行相关视图
@login_required
def code_execute(request):
    """代码执行页面"""
    # 获取用户的代码列表，供选择
    user_codes = Code.objects.filter(user=request.user).order_by('-created_at')

    # 获取支持的语言列表
    executor = CodeExecutor()
    supported_languages = executor.get_supported_languages()

    return render(
        request,
        'battles/code_execute.html',
        {
            'user_codes': user_codes,
            'supported_languages': supported_languages,
        },
    )


# 匹配相关辅助函数
def handle_realtime_match(request, code, round_limit, time_limit, is_public=True, save_round_inputs=False):
    """处理实时匹配"""
    # 查找等待中的实时匹配
    waiting_match = MatchQueue.objects.filter(match_mode='realtime', status='waiting').exclude(user=request.user).first()

    if waiting_match:
        # 找到匹配对手，创建对战
        battle = Battle.objects.create(
            player1=waiting_match.user,
            player2=request.user,
            player1_code=waiting_match.code,
            player2_code=code,
            status='pending',
            battle_type='ranked',
            is_public=is_public,
            save_round_inputs=save_round_inputs,
            map_config={'map': map_selection or settings.BATTLE_ENGINE.get('DEFAULT_MAP', 'main6')},
            game_config={'round_limit': round_limit, 'time_limit': time_limit, 'is_practice': False},
        )

        # 标记匹配完成
        waiting_match.mark_matched(battle)

        # 为当前用户也创建匹配记录
        current_user_match = MatchQueue.objects.create(
            user=request.user,
            code=code,
            match_mode='realtime',
            max_rounds=round_limit,
            time_limit=time_limit,
            expires_at=timezone.now() + timedelta(minutes=10),
        )
        current_user_match.mark_matched(battle)

        # 开始对战
        start_battle(battle)

        messages.success(request, f'匹配成功！正在与 {waiting_match.user.username} 对战。')
        return redirect('battles:battle_detail', battle_id=battle.id)
    else:
        # 没有找到对手，加入匹配队列
        match_queue = MatchQueue.objects.create(
            user=request.user,
            code=code,
            match_mode='realtime',
            max_rounds=round_limit,
            time_limit=time_limit,
            expires_at=timezone.now() + timedelta(minutes=10),  # 10分钟后过期
        )

        messages.info(request, '已加入匹配队列，正在等待对手...')
        return redirect('battles:match_status')


def handle_random_match(request, code, round_limit, time_limit, is_public=True, save_round_inputs=False, map_selection=None):
    """处理随机匹配 - 从公开代码中随机选择对手"""
    import random

    from django.db.models import Count, Q

    # 优先从有正常对局记录的公开代码中选择
    # 查询有成功完成对战记录的公开代码和星标代码
    codes_with_battles = (
        Code.objects.filter(
            Q(battles_as_code1__status='finished') | Q(battles_as_code2__status='finished'),
            Q(is_public=True) | Q(is_starred=True),
            is_active=True
        )
        .exclude(user=request.user)
        .annotate(
            battle_count1=Count('battles_as_code1', filter=Q(battles_as_code1__status='finished')),
            battle_count2=Count('battles_as_code2', filter=Q(battles_as_code2__status='finished')),
        )
        .distinct()
    )

    # 如果有经验丰富的代码，优先选择
    # 过滤出真正有对战记录的代码
    experienced_codes = [code for code in codes_with_battles if (code.battle_count1 + code.battle_count2) > 0]
    if experienced_codes:
        opponent_code = random.choice(experienced_codes)
    else:
        # 如果没有有经验的代码，从所有公开代码和星标代码中随机选择
        all_available_codes = Code.objects.filter(
            Q(is_public=True) | Q(is_starred=True),
            is_active=True
        ).exclude(user=request.user)

        if not all_available_codes.exists():
            messages.error(request, '当前没有可用的代码进行随机匹配。')
            return redirect('battles:battle_create')

        opponent_code = random.choice(list(all_available_codes))

    # 创建随机匹配对战
    battle = Battle.objects.create(
        player1=request.user,
        player2=opponent_code.user,
        player1_code=code,
        player2_code=opponent_code,
        status='pending',
        battle_type='ranked',
        is_public=is_public,
        save_round_inputs=save_round_inputs,
        map_config={'map': map_selection or settings.BATTLE_ENGINE.get('DEFAULT_MAP', 'main6')},
        game_config={'round_limit': round_limit, 'time_limit': time_limit, 'is_practice': False},
    )

    # 将排位赛添加到队列而不是直接开始
    from .battle_queue_manager import get_manual_battle_queue_manager
    queue_manager = get_manual_battle_queue_manager()
    queue_result = queue_manager.add_battle_to_queue(battle.id)

    if queue_result.get('success', False):
        messages.success(request, f'随机匹配成功！已加入队列等待执行，对手: {opponent_code.user.username} 的代码 "{opponent_code.title}"。')
    else:
        messages.warning(request, f'随机匹配成功，但加入队列时遇到问题：{queue_result.get("message", "未知错误")}。对手: {opponent_code.user.username} 的代码 "{opponent_code.title}"。')
    return redirect('battles:battle_detail', battle_id=battle.id)



def handle_practice_match(request, user_code, opponent_code_id, round_limit, time_limit, is_public=True, save_round_inputs=False, map_selection=None):
    """处理练习赛"""
    try:
        opponent_code = get_object_or_404(Code, id=opponent_code_id, is_active=True)

        # 检查对手代码是否可用
        # 星标代码默认可挑战，功能开关控制所有私有代码（包括非星标私有代码）
        if opponent_code.user != request.user:
            if FeatureSwitch.is_feature_enabled('private_code_challenge'):
                # 如果启用私有代码挑战，允许所有代码（公开、星标、私有）
                pass  # 所有代码都可用
            else:
                # 如果禁用私有代码挑战，允许公开代码和星标代码（星标代码默认可挑战）
                if not (opponent_code.is_public or opponent_code.is_starred):
                    disabled_message = FeatureSwitch.get_disabled_message('private_code_challenge')
                    messages.error(request, disabled_message)
                    return redirect('battles:battle_create')

        # 创建练习赛对战
        battle = Battle.objects.create(
            player1=request.user,
            player2=opponent_code.user,  # 对手可能是自己或其他用户
            player1_code=user_code,
            player2_code=opponent_code,
            battle_type='practice',
            status='pending',
            is_public=is_public,
            save_round_inputs=save_round_inputs,
            map_config={'map': map_selection or settings.BATTLE_ENGINE.get('DEFAULT_MAP', 'main6')},
            game_config={'round_limit': round_limit, 'time_limit': time_limit, 'is_practice': True},
        )

        # 将练习赛添加到队列而不是立即开始
        from .battle_queue_manager import get_manual_battle_queue_manager
        queue_manager = get_manual_battle_queue_manager()
        queue_result = queue_manager.add_battle_to_queue(battle.id)

        # 清理旧的练习赛记录（保留最近10场）
        cleanup_practice_battles(request.user)

        if queue_result.get('success', False):
            messages.success(request, f'练习赛已创建并加入队列！对手: {opponent_code.title}，等待执行中...')
        else:
            messages.warning(request, f'练习赛已创建，但加入队列时遇到问题：{queue_result.get("message", "未知错误")}。对手: {opponent_code.title}')
        return redirect('battles:battle_detail', battle_id=battle.id)

    except Exception as e:
        messages.error(request, f'创建练习赛失败: {str(e)}')
        return redirect('battles:battle_create')


def cleanup_practice_battles(user):
    """清理用户的练习赛记录，只保留最近10场"""
    practice_battles = Battle.objects.filter(player1=user, battle_type='practice').order_by('-created_at')

    # 如果超过10场，删除多余的
    if practice_battles.count() > 10:
        battles_to_delete = practice_battles[10:]
        for battle in battles_to_delete:
            battle.delete()


def start_battle(battle: Battle):
    """开始对战"""

    # 检查战斗状态，如果不是running，则设置为running
    if battle.status != 'running':
        battle.status = 'running'
        battle.started_at = timezone.now()
        battle.save()

    # 使用新的BattleEngine来处理战斗
    from .battle_engine import get_battle_engine_manager

    def run_battle_engine():
        """在新线程中运行同步战斗引擎"""
        try:
            manager = get_battle_engine_manager()
            success = manager.start_battle(str(battle.id))

            if not success:
                logger.error(f'Failed to start battle engine for battle {battle.id}')
                battle.status = 'error'
                battle.error_message = 'Failed to start battle engine'
                battle.save()

        except sqlite3.OperationalError as e:
            while str(e).find('database is locked') >= 0:
                try:
                    e = None
                    time.sleep(1)
                    battle.save()
                    logger.info(f'battle {battle.id} saved finally')
                except Exception as e2:
                    e = e2

        except Exception as e:
            logger.error(f'Error in battle {battle.id} engine thread: {e}')
            battle.status = 'error'
            battle.error_message = str(e)
            battle.save()

    # 在后台线程中执行战斗
    battle_thread = threading.Thread(target=run_battle_engine)
    battle_thread.daemon = True
    battle_thread.start()


@login_required
def match_status(request):
    """匹配状态页面"""
    current_match = MatchQueue.objects.filter(user=request.user, status='waiting').first()

    if not current_match:
        messages.info(request, '您当前没有进行中的匹配。')
        return redirect('battles:battle_create')

    return render(request, 'battles/match_status.html', {'current_match': current_match})


@login_required
def cancel_match(request):
    """取消匹配"""
    if request.method == 'POST':
        current_match = MatchQueue.objects.filter(user=request.user, status='waiting').first()

        if current_match:
            current_match.cancel()
            messages.success(request, '已取消匹配。')
        else:
            messages.warning(request, '没有找到进行中的匹配。')

    return redirect('battles:battle_create')


@require_GET
@login_required
def api_match_status(request):
    """获取匹配状态API"""
    current_match = MatchQueue.objects.filter(user=request.user, status='waiting').first()

    if not current_match:
        return JsonResponse({'status': 'no_match'})

    # 检查是否已匹配
    if current_match.status == 'matched' and current_match.matched_battle:
        return JsonResponse(
            {
                'status': 'matched',
                'battle_id': current_match.matched_battle.id,
                'redirect_url': f'/battles/{current_match.matched_battle.id}/',
            }
        )

    # 检查是否过期
    if current_match.is_expired():
        current_match.status = 'expired'
        current_match.save()
        return JsonResponse({'status': 'expired'})

    return JsonResponse(
        {
            'status': 'waiting',
            'mode': current_match.get_match_mode_display(),
            'created_at': current_match.created_at.isoformat(),
            'expires_at': current_match.expires_at.isoformat(),
        }
    )


@require_GET
@login_required
def api_manual_battle_queue_status(request):
    """API: 获取手动对战队列状态"""
    try:
        from django.apps import apps
        battles_config = apps.get_app_config('battles')

        if hasattr(battles_config, 'manual_queue_manager') and battles_config.manual_queue_manager:
            queue_status = battles_config.manual_queue_manager.get_queue_status()
            return JsonResponse({
                'success': True,
                'data': {
                    'in_progress': queue_status.get('running_count', 0),
                    'waiting_in_queue': queue_status.get('queue_count', 0),
                    'total_capacity': queue_status.get('max_queue_size', 10),
                    'max_concurrent': queue_status.get('max_concurrent_battles', 3)
                }
            })
        else:
            return JsonResponse({
                'success': False,
                'error': '队列管理器未初始化'
            })
    except Exception as e:
        logger.error(f"获取队列状态失败: {e}")
        return JsonResponse({
            'success': False,
            'error': '获取队列状态失败'
        })


@require_GET
def api_supported_languages(request):
    """API: 获取支持的编程语言列表"""
    executor = CodeExecutor()
    languages = executor.get_supported_languages()

    return JsonResponse({'success': True, 'languages': languages})


# ==================== Node.js 战斗服务器管理 API ====================


@csrf_exempt
@require_POST
@login_required
def create_node_battle_server(request):
    """创建并启动Node.js战斗服务器"""
    try:
        data = json.loads(request.body)
        battle_id = data.get('battle_id')
        config = data.get('config', {})

        if not battle_id:
            return JsonResponse({'success': False, 'error': 'battle_id is required'}, status=400)

        # 检查战斗是否存在且用户有权限
        try:
            battle = Battle.objects.get(id=battle_id)
            if request.user != battle.player1 and request.user != battle.player2 and not request.user.is_staff:
                return JsonResponse({'success': False, 'error': 'Permission denied'}, status=403)
        except Battle.DoesNotExist:
            return JsonResponse({'success': False, 'error': 'Battle not found'}, status=404)

        # 获取服务器管理器
        manager = get_node_server_manager()

        # 创建战斗服务器
        server = manager.create_battle_server(battle_id, config)
        if not server:
            return JsonResponse({'success': False, 'error': 'Failed to create battle server'}, status=500)

        # 启动服务器
        success = manager.start_battle_server(battle_id)
        if not success:
            return JsonResponse({'success': False, 'error': 'Failed to start battle server'}, status=500)

        # 更新战斗状态
        battle.status = 'running'
        battle.started_at = timezone.now()
        battle.save()

        logger.info(f'Node.js battle server created for battle {battle_id}')

        return JsonResponse(
            {
                'success': True,
                'message': 'Battle server created and started',
                'battle_id': battle_id,
                'server_status': server.get_status(),
            }
        )

    except json.JSONDecodeError:
        return JsonResponse({'success': False, 'error': 'Invalid JSON data'}, status=400)
    except Exception as e:
        logger.error(f'Error creating node battle server: {e}')
        return JsonResponse({'success': False, 'error': str(e)}, status=500)


@csrf_exempt
@require_POST
@login_required
def stop_node_battle_server(request):
    """停止Node.js战斗服务器"""
    try:
        data = json.loads(request.body)
        battle_id = data.get('battle_id')

        if not battle_id:
            return JsonResponse({'success': False, 'error': 'battle_id is required'}, status=400)

        # 检查权限
        try:
            battle = Battle.objects.get(id=battle_id)
            if request.user != battle.player1 and request.user != battle.player2 and not request.user.is_staff:
                return JsonResponse({'success': False, 'error': 'Permission denied'}, status=403)
        except Battle.DoesNotExist:
            return JsonResponse({'success': False, 'error': 'Battle not found'}, status=404)

        # 获取服务器管理器
        manager = get_node_server_manager()

        # 停止服务器
        success = manager.stop_battle_server(battle_id)

        # 更新战斗状态
        if battle.status == 'running':
            battle.status = 'finished'
            battle.finished_at = timezone.now()
            battle.save()

        logger.info(f'Node.js battle server stopped for battle {battle_id}')

        return JsonResponse(
            {
                'success': success,
                'message': 'Battle server stopped' if success else 'Failed to stop battle server',
                'battle_id': battle_id,
            }
        )

    except json.JSONDecodeError:
        return JsonResponse({'success': False, 'error': 'Invalid JSON data'}, status=400)
    except Exception as e:
        logger.error(f'Error stopping node battle server: {e}')
        return JsonResponse({'success': False, 'error': str(e)}, status=500)


@require_GET
@login_required
def get_node_battle_server_status(request, battle_id):
    """获取Node.js战斗服务器状态"""
    try:
        # 检查权限
        try:
            battle = Battle.objects.get(id=battle_id)
            if request.user != battle.player1 and request.user != battle.player2 and not request.user.is_staff:
                return JsonResponse({'success': False, 'error': 'Permission denied'}, status=403)
        except Battle.DoesNotExist:
            return JsonResponse({'success': False, 'error': 'Battle not found'}, status=404)

        # 获取服务器管理器
        manager = get_node_server_manager()

        # 获取服务器状态
        status = manager.get_server_status(battle_id)

        if status is None:
            return JsonResponse({'success': False, 'error': 'Battle server not found', 'battle_id': battle_id}, status=404)

        return JsonResponse({'success': True, 'battle_id': battle_id, 'status': status})

    except Exception as e:
        logger.error(f'Error getting node battle server status: {e}')
        return JsonResponse({'success': False, 'error': str(e)}, status=500)


@require_GET
@login_required
def list_node_battle_servers(request):
    """列出所有Node.js战斗服务器"""
    try:
        # 只有管理员可以查看所有服务器
        if not request.user.is_staff:
            return JsonResponse({'success': False, 'error': 'Permission denied'}, status=403)

        # 获取服务器管理器
        manager = get_node_server_manager()

        # 获取所有服务器状态
        servers = manager.list_servers()

        return JsonResponse({'success': True, 'servers': servers, 'total_count': len(servers)})

    except Exception as e:
        logger.error(f'Error listing node battle servers: {e}')
        return JsonResponse({'success': False, 'error': str(e)}, status=500)


@csrf_exempt
@require_POST
@login_required
def cleanup_node_battle_servers(request):
    """清理不健康的Node.js战斗服务器"""
    try:
        # 只有管理员可以执行清理
        if not request.user.is_staff:
            return JsonResponse({'success': False, 'error': 'Permission denied'}, status=403)

        # 获取服务器管理器
        manager = get_node_server_manager()

        # 执行清理
        manager.cleanup_unhealthy_servers()

        logger.info('Node.js battle servers cleanup completed')

        return JsonResponse({'success': True, 'message': 'Cleanup completed'})

    except Exception as e:
        logger.error(f'Error cleaning up node battle servers: {e}')
        return JsonResponse({'success': False, 'error': str(e)}, status=500)


@require_POST
@login_required
def api_command_validate(request):
    """验证前端发送的命令"""
    if request.method != 'POST':
        return JsonResponse({'error': '只支持POST请求'}, status=405)

    try:
        data = json.loads(request.body)
        command_type = data.get('commandType')
        unit_id = data.get('unitId')
        target_position = data.get('targetPosition')
        player_id = data.get('playerId')
        command_id = data.get('commandId')
        battle_id = data.get('battleId')

        # 记录日志
        logger.info(
            f'收到命令: {command_type}, 单位ID: {unit_id}, 目标位置: {target_position}, 玩家ID: {player_id}, 命令ID: {command_id}, 战斗ID: {battle_id}'
        )

        # TODO: 实现命令验证逻辑
        # 目前在测试阶段，简单返回验证通过
        is_valid = True

        # 如果验证通过，通过WebSocket广播命令
        if is_valid and battle_id:
            try:
                from asgiref.sync import async_to_sync
                from channels.layers import get_channel_layer

                channel_layer = get_channel_layer()
                battle_group_name = f'battle_{battle_id}'

                # 获取当前用户
                user = request.user

                # 广播命令到战斗组
                async_to_sync(channel_layer.group_send)(
                    battle_group_name,
                    {
                        'type': 'battle_command',
                        'command': data,
                        'user_id': user.id if user.is_authenticated else None,
                        'username': user.username if user.is_authenticated else 'Anonymous',
                    },
                )

                logger.info(f'命令已广播到WebSocket组: {battle_group_name}')
            except Exception as e:
                logger.error(f'WebSocket广播命令失败: {str(e)}')

        return JsonResponse({'valid': is_valid, 'commandId': command_id})

    except json.JSONDecodeError:
        return JsonResponse({'error': '无效的JSON格式'}, status=400)
    except Exception as e:
        logger.error(f'处理命令验证请求时出错: {str(e)}')
        return JsonResponse({'error': f'处理请求时出错: {str(e)}'}, status=500)


@login_required
def battle_iframe(request, battle_id):
    """
    嵌入Cocos战斗页面的视图
    """
    battle = get_object_or_404(Battle, id=battle_id)

    # 检查用户是否有权限查看该对战
    if not battle.is_public and request.user != battle.player1 and request.user != battle.player2 and not request.user.is_staff:
        messages.error(request, '您没有权限查看该对战')
        return redirect('battles:battle_list')

    context = {
        'battle': battle,
    }

    return render(request, 'battles/battle_iframe.html', context)


@require_GET
@login_required
def battle_ping(request, battle_id):
    """处理战斗页面的ping请求，防止服务断链"""
    battle = get_object_or_404(Battle, id=battle_id)

    # 检查用户是否有权限查看该对战
    if not battle.is_public and request.user != battle.player1 and request.user != battle.player2 and not request.user.is_staff:
        return JsonResponse({'status': 'error', 'message': '没有权限'}, status=403)

    return JsonResponse({'status': 'ok', 'message': 'pong'})


@require_GET
@login_required
def api_battle_execution_stats(request, battle_id):
    """获取战斗的代码执行统计信息API"""
    battle = get_object_or_404(Battle, id=battle_id)

    # 检查用户是否有权限查看该对战
    if not battle.is_public and request.user != battle.player1 and request.user != battle.player2 and not request.user.is_staff:
        return JsonResponse({'error': '没有权限查看此对战记录'}, status=403)

    try:
        stats = battle.get_execution_stats()
        return JsonResponse({'status': 'success', 'data': stats})
    except Exception as e:
        logger.error(f'获取战斗执行统计失败: {str(e)}')
        return JsonResponse({'error': '获取统计信息失败'}, status=500)


@require_GET
@login_required
def api_battle_stats(request, battle_id):
    """获取战斗的统计信息API"""
    battle = get_object_or_404(Battle, id=battle_id)

    # 检查用户是否有权限查看该对战
    if not battle.is_public and request.user != battle.player1 and request.user != battle.player2 and not request.user.is_staff:
        return JsonResponse({'error': '没有权限查看此对战记录'}, status=403)

    try:
        # 从player1_stats和player2_stats字段获取统计数据
        player1_stats = battle.player1_stats or {}
        player2_stats = battle.player2_stats or {}

        return JsonResponse({'status': 'success', 'data': {'player1': player1_stats, 'player2': player2_stats}})
    except Exception as e:
        logger.error(f'获取战斗统计失败: {str(e)}')
        return JsonResponse({'error': '获取统计信息失败'}, status=500)


@require_GET
@login_required
def api_battle_debug_log_download(request, battle_id):
    """下载战斗调试日志API"""
    battle = get_object_or_404(Battle, id=battle_id)

    # 检查用户是否有权限查看该对战
    if not battle.is_public and request.user != battle.player1 and request.user != battle.player2 and not request.user.is_staff:
        return JsonResponse({'error': '没有权限查看此对战记录'}, status=403)

    try:
        # 构建日志文件路径
        logs_dir = Path(__file__).parent.parent.parent / 'logs'
        debug_log_path = logs_dir / f'battle_debug_{battle.id}.log'

        # 检查文件是否存在
        if not debug_log_path.exists():
            return JsonResponse({'error': '调试日志文件不存在'}, status=404)

        # 读取文件内容
        try:
            with open(debug_log_path, 'r', encoding='utf-8') as f:
                log_content = f.read()
        except Exception as read_error:
            logger.warning(f'读取调试日志文件失败: {read_error}')
            return JsonResponse({'error': '读取日志文件失败'}, status=500)

        # 创建HTTP响应
        response = HttpResponse(log_content, content_type='text/plain; charset=utf-8')
        filename = f'battle_debug_{battle.id}.log'
        response['Content-Disposition'] = f'attachment; filename="{filename}"'

        return response

    except Exception as e:
        logger.error(f'下载调试日志失败: {str(e)}')
        return JsonResponse({'error': '下载日志失败'}, status=500)


@require_GET
@login_required
def api_battle_server_log_download(request, battle_id):
    """下载战斗服务器日志API"""
    battle = get_object_or_404(Battle, id=battle_id)

    # 检查用户是否有权限查看该对战
    if not battle.is_public and request.user != battle.player1 and request.user != battle.player2 and not request.user.is_staff:
        return JsonResponse({'error': '没有权限查看此对战记录'}, status=403)

    try:
        # 构建日志文件路径
        logs_dir = Path(__file__).parent.parent.parent / 'logs'
        server_log_path = logs_dir / f'battle_server_{battle.id}.log'

        # 检查文件是否存在
        if not server_log_path.exists():
            return JsonResponse({'error': '服务器日志文件不存在'}, status=404)

        # 读取文件内容
        try:
            with open(server_log_path, 'r', encoding='utf-8') as f:
                log_content = f.read()
        except Exception as read_error:
            logger.warning(f'读取服务器日志文件失败: {read_error}')
            return JsonResponse({'error': '读取日志文件失败'}, status=500)

        # 创建HTTP响应
        response = HttpResponse(log_content, content_type='text/plain; charset=utf-8')
        filename = f'battle_server_{battle.id}.log'
        response['Content-Disposition'] = f'attachment; filename="{filename}"'

        return response

    except Exception as e:
        logger.error(f'下载服务器日志失败: {str(e)}')
        return JsonResponse({'error': '下载日志失败'}, status=500)


@require_GET
@login_required
def api_battle_report_download(request, battle_id):
    """下载战斗所有命令API（包括init和end命令）"""
    battle = get_object_or_404(Battle, id=battle_id)

    # 检查用户是否有权限查看该对战
    if not battle.is_public and request.user != battle.player1 and request.user != battle.player2 and not request.user.is_staff:
        return JsonResponse({'error': '没有权限查看此对战记录'}, status=403)

    try:
        # 构建allActions数组，与前端回放逻辑一致
        all_actions = []

        # 添加init_command
        if hasattr(battle, 'init_command') and battle.init_command:
            all_actions.append(battle.init_command)

        # 获取所有回合数据并添加每回合的命令
        rounds = battle.rounds.all().order_by('round_number')

        for round_obj in rounds:
            # 添加玩家1的命令
            if round_obj.player1_actions:
                try:
                    if isinstance(round_obj.player1_actions, str):
                        actions = json.loads(round_obj.player1_actions)
                    else:
                        actions = round_obj.player1_actions

                    if isinstance(actions, list):
                        all_actions.extend(actions)
                    else:
                        all_actions.append(actions)
                except (json.JSONDecodeError, TypeError):
                    all_actions.append(round_obj.player1_actions)

            # 添加玩家2的命令
            if round_obj.player2_actions:
                try:
                    if isinstance(round_obj.player2_actions, str):
                        actions = json.loads(round_obj.player2_actions)
                    else:
                        actions = round_obj.player2_actions

                    if isinstance(actions, list):
                        all_actions.extend(actions)
                    else:
                        all_actions.append(actions)
                except (json.JSONDecodeError, TypeError):
                    all_actions.append(round_obj.player2_actions)

        # 添加end_command
        if hasattr(battle, 'end_command') and battle.end_command:
            all_actions.append(battle.end_command)

        # 将每个命令转换为一行字符串
        command_lines = []
        for action in all_actions:
            if isinstance(action, (dict, list)):
                command_lines.append(json.dumps(action, ensure_ascii=False, separators=(',', ':')))
            else:
                command_lines.append(str(action))

        commands_content = '\n'.join(command_lines)

        # 创建HTTP响应
        response = HttpResponse(commands_content, content_type='text/plain; charset=utf-8')
        filename = f'battle_{battle.id}_all_commands.txt'
        response['Content-Disposition'] = f'attachment; filename="{filename}"'

        return response

    except Exception as e:
        logger.error(f'下载战斗所有命令失败: {str(e)}')
        return JsonResponse({'error': '下载所有命令失败'}, status=500)


@require_GET
@login_required
def api_user_execution_logs(request):
    """获取用户的执行日志列表API"""
    try:
        from .models import BattleExecutionLog

        # 获取用户最近50场的日志
        logs = BattleExecutionLog.objects.filter(user=request.user).order_by('-created_at')[:50]

        logs_data = []
        for log in logs:
            logs_data.append(
                {
                    'id': log.id,
                    'battle_id': log.battle.id,
                    'battle_info': f'{log.battle.player1.username} vs {log.battle.player2.username}',
                    'log_type': log.log_type,
                    'total_commands': log.total_commands,
                    'successful_commands': log.successful_commands,
                    'failed_commands': log.failed_commands,
                    'success_rate': (log.successful_commands / log.total_commands * 100) if log.total_commands > 0 else 0,
                    'created_at': log.created_at.isoformat(),
                }
            )

        return JsonResponse({'status': 'success', 'data': logs_data})

    except Exception as e:
        logger.error(f'获取用户执行日志失败: {str(e)}')
        return JsonResponse({'error': '获取日志列表失败'}, status=500)


@require_GET
@login_required
def api_battle_rounds(request, battle_id):
    """获取战斗回合数据API"""
    try:
        battle = get_object_or_404(Battle, id=battle_id)

        # 检查用户是否有权限查看该对战
        if (
            not battle.is_public
            and request.user != battle.player1
            and request.user != battle.player2
            and not request.user.is_staff
        ):
            return JsonResponse({'error': '没有权限查看此对战'}, status=403)

        # 获取查询参数
        start_round = request.GET.get('start', 1)
        end_round = request.GET.get('end', None)
        filter_type = request.GET.get('filter', '')

        try:
            start_round = int(start_round)
            if end_round:
                end_round = int(end_round)
        except ValueError:
            return JsonResponse({'error': '无效的回合参数'}, status=400)

        # 查询回合数据
        rounds_query = battle.rounds.filter(round_number__gte=start_round)
        if end_round:
            rounds_query = rounds_query.filter(round_number__lte=end_round)

        # 应用筛选条件
        if filter_type == 'error-or-failed':
            # 筛选有错误或失败命令的回合
            from django.db.models import Q

            rounds_query = rounds_query.filter(
                Q(player1_failed_commands__gt=0)
                | Q(player2_failed_commands__gt=0)
                | Q(player1_command_execution_details__icontains='"success": false')
                | Q(player2_command_execution_details__icontains='"success": false')
                | Q(player1_command_execution_details__icontains='"exception_type"')
                | Q(player2_command_execution_details__icontains='"exception_type"')
                | Q(player1_command_execution_details__icontains='"exception_message"')
                | Q(player2_command_execution_details__icontains='"exception_message"')
                | Q(player1_command_execution_details__icontains='"error_type"')
                | Q(player2_command_execution_details__icontains='"error_type"')
            )
        elif filter_type == 'player1-error-or-failed':
            # 筛选玩家1有错误或失败命令的回合
            from django.db.models import Q

            rounds_query = rounds_query.filter(
                Q(player1_failed_commands__gt=0)
                | Q(player1_command_execution_details__icontains='"success": false')
                | Q(player1_command_execution_details__icontains='"exception_type"')
                | Q(player1_command_execution_details__icontains='"exception_message"')
                | Q(player1_command_execution_details__icontains='"error_type"')
            )
        elif filter_type == 'player2-error-or-failed':
            # 筛选玩家2有错误或失败命令的回合
            from django.db.models import Q

            rounds_query = rounds_query.filter(
                Q(player2_failed_commands__gt=0)
                | Q(player2_command_execution_details__icontains='"success": false')
                | Q(player2_command_execution_details__icontains='"exception_type"')
                | Q(player2_command_execution_details__icontains='"exception_message"')
                | Q(player2_command_execution_details__icontains='"error_type"')
            )

        rounds = rounds_query.order_by('round_number')

        # 构建响应数据
        rounds_data = []
        for round_obj in rounds:
            round_data = {
                'round_number': round_obj.round_number,
                'timestamp': round_obj.timestamp.strftime('%Y-%m-%d %H:%M:%S'),
                'player1_successful_commands': round_obj.player1_successful_commands,
                'player1_failed_commands': round_obj.player1_failed_commands,
                'player2_successful_commands': round_obj.player2_successful_commands,
                'player2_failed_commands': round_obj.player2_failed_commands,
                'player1_actions': round_obj.player1_actions or [],
                'player2_actions': round_obj.player2_actions or [],
                'player1_command_execution_details': round_obj.player1_command_execution_details or [],
                'player2_command_execution_details': round_obj.player2_command_execution_details or [],
                'player1_battle_state': round_obj.player1_battle_state or {},
                'player2_battle_state': round_obj.player2_battle_state or {},
                # 添加原api_battle_rounds_data接口中的额外字段以保持兼容性
                'player1_units': round_obj.player1_units,
                'player2_units': round_obj.player2_units,
                'round_data': round_obj.round_data,
            }
            rounds_data.append(round_data)

        return JsonResponse({'status': 'success', 'data': rounds_data})

    except Exception as e:
        logger.error(f'获取战斗回合数据失败: {str(e)}')
        return JsonResponse({'error': '获取回合数据失败'}, status=500)


@require_GET
@login_required
def api_user_detailed_stats(request):
    """API: 获取用户详细统计信息"""
    try:
        # 获取或创建用户的对战统计
        stats, created = BattleStatistics.objects.get_or_create(user=request.user)

        # 获取详细统计信息
        detailed_stats = stats.get_detailed_stats()

        return JsonResponse(
            {
                'status': 'success',
                'data': {
                    'basic_stats': {
                        'total_battles': stats.total_battles,
                        'wins': stats.wins,
                        'losses': stats.losses,
                        'draws': stats.draws,
                        'win_rate': stats.get_win_rate(),
                        'total_score': stats.total_score,
                        'average_score': stats.average_score,
                        'best_score': stats.best_score,
                        'rating': stats.rating,
                    },
                    'detailed_stats': detailed_stats,
                    'kd_ratio': stats.get_kd_ratio(),
                },
            }
        )

    except Exception as e:
        logger.error(f'获取用户详细统计信息失败: {str(e)}')
        return JsonResponse({'error': '获取统计信息失败'}, status=500)


# ==================== 世界杯相关视图 ====================

@login_required
def worldcup_list(request):
    """世界杯列表页面"""
    worldcups = WorldCup.objects.all().order_by('-created_at')

    # 为每个世界杯添加冠军信息
    for worldcup in worldcups:
        if worldcup.status == 'finished':
            # 获取冠军（championship_rank = 1）
            champion = worldcup.participants.filter(championship_rank=1).first()
            worldcup.champion = champion
        else:
            worldcup.champion = None

    # 分页处理
    paginator = Paginator(worldcups, 10)
    page_number = request.GET.get('page')
    page_obj = paginator.get_page(page_number)

    return render(request, 'battles/worldcup_list.html', {
        'page_obj': page_obj,
    })


@login_required
def admin_worldcup_create(request):
    """管理员创建世界杯"""
    # 检查管理员权限
    if not request.user.is_staff:
        messages.error(request, '您没有权限执行此操作。')
        return redirect('battles:worldcup_list')

    if request.method == 'POST':
        name = request.POST.get('name', '').strip()
        description = request.POST.get('description', '').strip()
        max_rounds = request.POST.get('round_limit', 100)
        time_limit = request.POST.get('time_limit', 30)

        # 验证输入
        if not name:
            messages.error(request, '世界杯名称不能为空。')
            return redirect('battles:worldcup_list')

        try:
            max_rounds = int(max_rounds)
            time_limit = int(time_limit)

            if max_rounds <= 0 or max_rounds > 1000:
                messages.error(request, '最大回合数必须在1-1000之间。')
                return redirect('battles:worldcup_list')

            if time_limit <= 0 or time_limit > 300:
                messages.error(request, '时间限制必须在1-300秒之间。')
                return redirect('battles:worldcup_list')
        except ValueError:
            messages.error(request, '请输入有效的数字。')
            return redirect('battles:worldcup_list')

        # 创建世界杯
        try:
            worldcup = WorldCup.objects.create(
                name=name,
                description=description,
                round_limit=max_rounds,
                time_limit=time_limit,
                status='preparing'
            )
            messages.success(request, f'世界杯 "{name}" 创建成功！')
            return redirect('battles:worldcup_detail', worldcup_id=worldcup.id)
        except Exception as e:
            logger.error(f'创建世界杯失败: {e}')
            messages.error(request, '创建世界杯失败，请稍后重试。')
            return redirect('battles:worldcup_list')

    # GET请求，显示创建表单
    return render(request, 'battles/worldcup_create.html')


@csrf_exempt
@require_POST
@login_required
def admin_worldcup_delete(request, worldcup_id):
    """管理员删除世界杯"""
    # 检查管理员权限
    if not request.user.is_staff:
        return JsonResponse({'success': False, 'message': '您没有权限执行此操作。'}, status=403)

    try:
        worldcup = get_object_or_404(WorldCup, id=worldcup_id)

        # 检查世界杯状态，如果正在进行中则不允许删除
        if worldcup.status in ['regular_season', 'championship']:
            return JsonResponse({
                'success': False,
                'message': '世界杯正在进行中，无法删除。请先结束比赛或等待比赛完成。'
            }, status=400)

        worldcup_name = worldcup.name

        # 删除世界杯（级联删除相关数据）
        worldcup.delete()

        logger.info(f'管理员 {request.user.username} 删除了世界杯: {worldcup_name}')

        return JsonResponse({
            'success': True,
            'message': f'世界杯 "{worldcup_name}" 已成功删除。'
        })

    except Exception as e:
        logger.error(f'删除世界杯失败: {e}')
        return JsonResponse({
            'success': False,
            'message': '删除世界杯失败，请稍后重试。'
        }, status=500)


@login_required
def worldcup_detail(request, worldcup_id):
    """世界杯详情页面"""
    worldcup = get_object_or_404(WorldCup, id=worldcup_id)

    # 获取参赛者信息
    participants = worldcup.participants.all().order_by('-wins', '-total_score')

    # 获取常规赛对战记录
    regular_season_battles = Battle.objects.filter(
        battle_type='worldcup_regular',
        worldcupmatch__worldcup=worldcup
    ).order_by('-created_at')[:10]  # 最近10场

    # 获取冠军赛对战记录
    championship_battles = Battle.objects.filter(
        battle_type='worldcup_championship',
        worldcupmatch__worldcup=worldcup
    ).order_by('-created_at')[:10]  # 最近10场

    # 计算各个淘汰赛阶段的开始和结束时间
    stage_times = {}
    stages = ['round_16', 'quarter_final', 'semi_final', 'final']

    for stage in stages:
        stage_matches = WorldCupMatch.objects.filter(
            worldcup=worldcup,
            stage=stage
        ).order_by('created_at')

        if stage_matches.exists():
            # 阶段开始时间：第一场比赛实际开始战斗的时间（有关联的Battle记录且Battle已开始）
            started_matches = stage_matches.filter(
                battle__isnull=False,
                battle__started_at__isnull=False
            ).order_by('battle__started_at')

            if started_matches.exists():
                stage_times[f'{stage}_started_at'] = started_matches.first().battle.started_at

            # 阶段结束时间：最后一场比赛的完成时间（如果所有比赛都完成了）
            completed_matches = stage_matches.filter(is_completed=True)
            if completed_matches.count() == stage_matches.count() and completed_matches.exists():
                stage_times[f'{stage}_finished_at'] = completed_matches.order_by('-completed_at').first().completed_at

    # 获取冠军赛各阶段的详细信息
    championship_stages_info = {}
    if worldcup.status == 'championship':
        stage_names = {
            'round_16': '16强',
            'quarter_final': '8强',
            'semi_final': '4强',
            'final': '决赛'
        }

        for stage in stages:
            stage_matches = WorldCupMatch.objects.filter(
                worldcup=worldcup,
                stage=stage
            )

            if stage_matches.exists():
                total_matches = stage_matches.count()
                completed_matches = stage_matches.filter(is_completed=True).count()
                running_matches = stage_matches.filter(
                    battle__isnull=False,
                    battle__status='running'
                ).count()
                pending_matches = stage_matches.filter(
                    battle__isnull=False,
                    battle__status='pending'
                ).count()

                # 确定阶段状态
                if completed_matches == total_matches:
                    stage_status = 'completed'
                elif running_matches > 0 or pending_matches > 0:
                    stage_status = 'in_progress'
                elif stage_matches.filter(battle__isnull=True).exists():
                    stage_status = 'not_started'
                else:
                    stage_status = 'waiting'

                championship_stages_info[stage] = {
                    'name': stage_names[stage],
                    'total_matches': total_matches,
                    'completed_matches': completed_matches,
                    'running_matches': running_matches,
                    'pending_matches': pending_matches,
                    'status': stage_status,
                    'progress_percentage': round((completed_matches / total_matches) * 100, 1) if total_matches > 0 else 0
                }

    return render(request, 'battles/worldcup_detail.html', {
        'worldcup': worldcup,
        'participants': participants,
        'regular_season_battles': regular_season_battles,
        'championship_battles': championship_battles,
        'championship_stages_info': championship_stages_info,
        **stage_times,  # 将各阶段时间添加到模板上下文
    })


@login_required
def worldcup_regular_season(request, worldcup_id):
    """世界杯常规赛排行榜页面"""
    worldcup = get_object_or_404(WorldCup, id=worldcup_id)

    # 获取参赛者排行榜（按胜场、积分排序）
    participants = worldcup.participants.all().order_by(
        '-wins',
        '-total_score',
        'losses'
    )

    # 计算每个参赛者的胜率和总对战数
    for participant in participants:
        total_battles = participant.wins + participant.losses + participant.draws
        participant.total_battles = total_battles
        if total_battles > 0:
            participant.win_rate = round((participant.wins / total_battles) * 100, 1)
        else:
            participant.win_rate = 0

    # 获取常规赛对战记录
    regular_season_matches = WorldCupMatch.objects.filter(
        worldcup=worldcup,
        stage='regular'
    ).order_by('-created_at')

    # 计算统计数据
    total_matches = regular_season_matches.count()
    completed_matches = regular_season_matches.filter(is_completed=True).count()

    # 计算各种状态的对战数
    error_matches = regular_season_matches.filter(battle__status='error').count()
    running_matches = regular_season_matches.filter(battle__status='running').count()
    waiting_matches = regular_season_matches.filter(battle__status='pending').count()

    # 计算完成进度
    if total_matches > 0:
        progress = round((completed_matches / total_matches) * 100, 1)
    else:
        progress = 0

    # 分页处理对战记录
    paginator = Paginator(regular_season_matches, 20)
    page_number = request.GET.get('page')
    page_obj = paginator.get_page(page_number)

    return render(request, 'battles/worldcup_regular_season.html', {
        'worldcup': worldcup,
        'participants': participants,
        'page_obj': page_obj,
        'completed_matches': completed_matches,
        'total_matches': total_matches,
        'progress': progress,
        'error_matches': error_matches,
        'running_matches': running_matches,
        'waiting_matches': waiting_matches,
    })


@login_required
def worldcup_championship(request, worldcup_id):
    """世界杯冠军赛对战图页面"""
    worldcup = get_object_or_404(WorldCup, id=worldcup_id)

    # 获取冠军赛对战记录，按阶段和创建时间排序
    championship_matches = WorldCupMatch.objects.filter(
        worldcup=worldcup,
        stage__in=['round_16', 'quarter_final', 'semi_final', 'final']
    ).order_by('stage', 'created_at')

    # 按阶段分组
    matches_by_stage = {
        'round_16': [],
        'quarter_final': [],
        'semi_final': [],
        'final': []
    }

    for match in championship_matches:
        matches_by_stage[match.stage].append(match)

    # 获取最终排名（前4名）
    top_participants = worldcup.participants.filter(
        championship_rank__lte=4
    ).order_by('championship_rank')

    # 获取完整的冠军赛排行榜（所有进入冠军赛的选手）
    championship_rankings = []

    # 如果冠军赛已经开始或结束，获取所有进入冠军赛的参赛者
    if worldcup.status in ['championship', 'finished'] and championship_matches.exists():
        # 获取所有进入冠军赛的参赛者（16强及以上）
        championship_participants = worldcup.participants.filter(
            stage__in=['round_16', 'quarter_final', 'semi_final', 'final']
        ).distinct()

        # 为每个参赛者计算排行榜信息
        for participant in championship_participants:
            # 计算冠军赛胜场数
            championship_wins = 0

            # 统计在冠军赛中的胜场
            won_matches = WorldCupMatch.objects.filter(
                worldcup=worldcup,
                stage__in=['round_16', 'quarter_final', 'semi_final', 'final'],
                winner=participant,
                is_completed=True
            )
            championship_wins = won_matches.count()

            # 确定淘汰阶段
            eliminated_stage = None
            if participant.is_eliminated:
                eliminated_stage = participant.eliminated_at_stage
            elif participant.championship_rank:
                # 根据最终排名确定淘汰阶段
                if participant.championship_rank == 1:
                    eliminated_stage = None  # 冠军
                elif participant.championship_rank == 2:
                    eliminated_stage = 'final'  # 决赛失败
                elif participant.championship_rank in [3, 4]:
                    eliminated_stage = 'semi_final'  # 半决赛失败
                elif participant.championship_rank in [5, 6, 7, 8]:
                    eliminated_stage = 'quarter_final'  # 8强失败
                else:
                    eliminated_stage = 'round_16'  # 16强失败

            championship_rankings.append({
                'participant': participant,
                'championship_wins': championship_wins,
                'regular_season_rank': None,  # 将在下面计算
                'eliminated_stage': eliminated_stage,
                'final_rank': participant.championship_rank or 999,  # 未设置排名的放在最后
            })

        # 计算常规赛排名（用于相同胜场数时的排序）
        # 注意：不能使用stage='regular'筛选，因为进入冠军赛的参赛者stage已经被更新
        # 使用所有参赛者的常规赛数据（wins和total_score）进行排名
        regular_season_participants = list(worldcup.participants.order_by(
            '-wins', '-total_score'
        ))

        # 为每个冠军赛参赛者设置常规赛排名
        for ranking in championship_rankings:
            try:
                regular_rank = regular_season_participants.index(ranking['participant']) + 1
                ranking['regular_season_rank'] = regular_rank
            except ValueError:
                ranking['regular_season_rank'] = 999

        # 排序规则：
        # 1. 冠军赛胜场数（降序）
        # 2. 常规赛排名（升序）- 胜场相同时按常规赛排名排序
        # 3. 最终排名（升序）- 作为最后的排序依据
        championship_rankings.sort(key=lambda x: (
            -x['championship_wins'],  # 冠军赛胜场数降序（主要排序依据）
            x['regular_season_rank'],  # 常规赛排名升序（胜场相同时的排序依据）
            x['final_rank']  # 最终排名升序（最后的排序依据）
        ))

        # 按照新的排序结果分配显示排名
        # 考虑并列排名的情况（相同胜场数和常规赛排名的参赛者应该有相同的排名）
        current_rank = 1
        for i, ranking in enumerate(championship_rankings):
            if i > 0:
                prev_ranking = championship_rankings[i-1]
                # 如果当前参赛者的胜场数和常规赛排名都与前一个相同，则排名相同
                if (ranking['championship_wins'] == prev_ranking['championship_wins'] and
                    ranking['regular_season_rank'] == prev_ranking['regular_season_rank']):
                    ranking['display_rank'] = prev_ranking['display_rank']
                else:
                    current_rank = i + 1
                    ranking['display_rank'] = current_rank
            else:
                ranking['display_rank'] = current_rank

    return render(request, 'battles/worldcup_championship.html', {
        'worldcup': worldcup,
        'matches_by_stage': matches_by_stage,
        'top_participants': top_participants,
        'championship_rankings': championship_rankings,
    })


@login_required
def worldcup_battles(request, worldcup_id):
    """世界杯对战记录页面"""
    worldcup = get_object_or_404(WorldCup, id=worldcup_id)

    # 获取所有常规赛对战记录
    battles = Battle.objects.filter(
        battle_type='worldcup_regular',
        worldcupmatch__worldcup=worldcup
    ).select_related('player1', 'player2', 'player1_code', 'player2_code').order_by('-created_at')

    # 获取筛选参数
    search_query = request.GET.get('search', '').strip()
    status_filter = request.GET.get('status', '')

    # 应用筛选
    if search_query:
        battles = battles.filter(
            Q(player1__username__icontains=search_query) |
            Q(player2__username__icontains=search_query)
        )

    if status_filter:
        battles = battles.filter(status=status_filter)

    # 计算统计数据
    total_battles = battles.count()
    finished_battles = battles.filter(status='finished').count()
    running_battles = battles.filter(status='running').count()
    pending_battles = battles.filter(status='pending').count()
    error_battles = battles.filter(status='error').count()

    # 分页处理
    paginator = Paginator(battles, 20)
    page_number = request.GET.get('page')
    page_obj = paginator.get_page(page_number)

    return render(request, 'battles/worldcup_battles.html', {
        'worldcup': worldcup,
        'page_obj': page_obj,
        'total_battles': total_battles,
        'finished_battles': finished_battles,
        'running_battles': running_battles,
        'pending_battles': pending_battles,
        'error_battles': error_battles,
        'search_query': search_query,
        'status_filter': status_filter,
    })


@require_GET
@login_required
def api_worldcup_regular_season_data(request, worldcup_id):
    """API: 获取世界杯常规赛实时数据"""
    try:
        worldcup = get_object_or_404(WorldCup, id=worldcup_id)

        # 获取参赛者排行榜数据
        participants_data = []
        for participant in worldcup.participants.all().order_by(
            '-wins',
            '-total_score',
            'losses'
        ):
            participants_data.append({
                'id': participant.id,
                'user_id': participant.user.id,
                'username': participant.user.username,
                'code_id': participant.code.id,
                'code_title': participant.code.title,
                'wins': participant.wins,
                'losses': participant.losses,
                'score': participant.total_score,
                'total_battles': participant.wins + participant.losses + participant.draws,
                'win_rate': round(
                     (participant.wins / max(1, participant.wins + participant.losses + participant.draws)) * 100,
                     1
                 ),
            })

        # 获取最近的对战结果
        recent_matches = []
        for match in WorldCupMatch.objects.filter(
            worldcup=worldcup,
            stage='regular'
        ).order_by('-created_at')[:10]:
            if match.battle:
                recent_matches.append({
                    'id': match.id,
                    'battle_id': match.battle.id,
                    'player1': match.battle.player1.username,
                    'player2': match.battle.player2.username,
                    'result': match.battle.result,
                    'status': match.battle.status,
                    'created_at': match.battle.created_at.isoformat(),
                })

        # 获取进度统计数据
        all_regular_matches = WorldCupMatch.objects.filter(
            worldcup=worldcup,
            stage='regular'
        )

        total_matches = all_regular_matches.count()
        finished_matches = all_regular_matches.filter(battle__status='finished').count()
        running_matches = all_regular_matches.filter(battle__status='running').count()
        pending_matches = all_regular_matches.filter(battle__status='pending').count()
        error_matches = all_regular_matches.filter(battle__status='error').count()

        progress_percentage = round((finished_matches / max(1, total_matches)) * 100, 1) if total_matches > 0 else 0

        progress_data = {
            'total_matches': total_matches,
            'finished_battles': finished_matches,
            'running_battles': running_matches,
            'pending_battles': pending_matches,
            'error_battles': error_matches,
            'progress': progress_percentage
        }

        return JsonResponse({
            'status': 'success',
            'data': {
                'worldcup_status': worldcup.status,
                'participants': participants_data,
                'recent_matches': recent_matches,
                'progress': progress_data,
                'total_participants': worldcup.participants.count(),
            }
        })

    except Exception as e:
        logger.error(f'获取世界杯常规赛数据失败: {str(e)}')
        return JsonResponse({'error': '获取数据失败'}, status=500)


@require_GET
@login_required
def api_worldcup_championship_data(request, worldcup_id):
    """API: 获取世界杯冠军赛实时数据"""
    try:
        worldcup = get_object_or_404(WorldCup, id=worldcup_id)

        # 获取冠军赛对战数据，按阶段分组
        championship_data = {
            'round_16': [],
            'quarter_final': [],
            'semi_final': [],
            'final': []
        }

        for match in WorldCupMatch.objects.filter(
            worldcup=worldcup,
            stage__in=['round_16', 'quarter_final', 'semi_final', 'final']
        ).order_by('stage', 'created_at'):
            match_data = {
                'id': match.id,
                'stage': match.stage,
                'player1': match.participant1.user.username if match.participant1 else None,
                'player2': match.participant2.user.username if match.participant2 else None,
                'winner': match.winner.user.username if match.winner else None,
                'status': 'completed' if match.is_completed else ('running' if match.battle and match.battle.status == 'running' else 'pending'),
                'battle_id': match.battle.id if match.battle else None,
                'battle_status': match.battle.status if match.battle else None,
                'battle_result': match.battle.result if match.battle else None,
                'created_at': match.created_at.isoformat(),
            }
            championship_data[match.stage].append(match_data)

        # 获取最终排名（有冠军赛排名的参赛者）
        rankings = []
        for participant in worldcup.participants.filter(
            championship_rank__isnull=False
        ).order_by('championship_rank'):
            rankings.append({
                'rank': participant.championship_rank,
                'username': participant.user.username,
                'regular_season_score': participant.total_score,
                'regular_season_wins': participant.wins,
            })

        # 获取所有参赛选手数据（用于参赛选手模块显示）
        participants_data = []
        for participant in worldcup.participants.all().order_by('-wins', '-total_score'):
            participants_data.append({
                'id': participant.id,
                'user_id': participant.user.id,
                'username': participant.user.username,
                'code_id': participant.code.id,
                'code_title': participant.code.title,
                'wins': participant.wins,
                'losses': participant.losses,
                'draws': participant.draws,
                'total_score': participant.total_score,
                'championship_rank': participant.championship_rank,
                'is_eliminated': participant.is_eliminated,
                'eliminated_at_stage': participant.eliminated_at_stage,
                # 计算胜率
                'win_rate': round((participant.wins / (participant.wins + participant.losses + participant.draws)) * 100, 1) if (participant.wins + participant.losses + participant.draws) > 0 else 0,
            })

        return JsonResponse({
            'status': 'success',
            'data': {
                'worldcup_status': worldcup.status,
                'championship_matches': championship_data,
                'rankings': rankings,
                'participants': participants_data,  # 添加完整的参赛选手数据
            }
        })

    except Exception as e:
        logger.error(f'获取世界杯冠军赛数据失败: {str(e)}')
        return JsonResponse({'error': '获取数据失败'}, status=500)


@require_GET
@login_required
def api_worldcup_detail(request, worldcup_id):
    """API: 获取世界杯详情数据"""
    try:
        worldcup = get_object_or_404(WorldCup, id=worldcup_id)

        # 获取参赛者信息
        participants_data = []
        for participant in worldcup.participants.all().order_by('-wins', '-total_score'):
            participants_data.append({
                'id': participant.id,
                'user_id': participant.user.id,
                'username': participant.user.username,
                'code_id': participant.code.id,
                'code_title': participant.code.title,
                'wins': participant.wins,
                'losses': participant.losses,
                'draws': participant.draws,
                'total_score': participant.total_score,
                'championship_rank': participant.championship_rank,
                'is_eliminated': participant.is_eliminated,
                'eliminated_at_stage': participant.eliminated_at_stage,
            })

        # 获取常规赛对战记录
        regular_season_battles_data = []
        for battle in Battle.objects.filter(
            battle_type='worldcup_regular',
            worldcupmatch__worldcup=worldcup
        ).order_by('-created_at')[:10]:
            regular_season_battles_data.append({
                'id': battle.id,
                'status': battle.status,
                'result': battle.result,
                'player1': battle.player1.username if battle.player1 else None,
                'player2': battle.player2.username if battle.player2 else None,
                'winner': battle.winner.username if battle.winner else None,
                'created_at': battle.created_at.isoformat(),
                'finished_at': battle.finished_at.isoformat() if battle.finished_at else None,
            })

        # 获取冠军赛对战记录
        championship_battles_data = []
        for battle in Battle.objects.filter(
            battle_type='worldcup_championship',
            worldcupmatch__worldcup=worldcup
        ).order_by('-created_at')[:10]:
            championship_battles_data.append({
                'id': battle.id,
                'status': battle.status,
                'result': battle.result,
                'player1': battle.player1.username if battle.player1 else None,
                'player2': battle.player2.username if battle.player2 else None,
                'winner': battle.winner.username if battle.winner else None,
                'created_at': battle.created_at.isoformat(),
                'finished_at': battle.finished_at.isoformat() if battle.finished_at else None,
            })

        return JsonResponse({
            'status': 'success',
            'data': {
                'worldcup': {
                    'id': worldcup.id,
                    'name': worldcup.name,
                    'description': worldcup.description,
                    'status': worldcup.status,
                    'max_participants': worldcup.max_participants,
                    'created_at': worldcup.created_at.isoformat(),
                    'started_at': worldcup.started_at.isoformat() if worldcup.started_at else None,
                    'finished_at': worldcup.finished_at.isoformat() if worldcup.finished_at else None,
                },
                'participants': participants_data,
                'regular_season_battles': regular_season_battles_data,
                'championship_battles': championship_battles_data,
            }
        })

    except Exception as e:
        logger.error(f'获取世界杯详情数据失败: {str(e)}')
        return JsonResponse({'error': '获取数据失败'}, status=500)


@require_GET
@login_required
def api_worldcup_stage_transition_status(request, worldcup_id):
    """获取世界杯阶段转换状态"""
    try:
        worldcup = get_object_or_404(WorldCup, id=worldcup_id)

        # 获取阶段转换信息
        stage_transition_info = worldcup.stage_transition_info or {}

        # 检查是否正在进行阶段转换
        is_transitioning = stage_transition_info.get('countdown_active', False)

        if is_transitioning:
            # 计算剩余时间
            start_time_str = stage_transition_info.get('start_time')
            if start_time_str:
                from datetime import datetime
                start_time = datetime.fromisoformat(start_time_str.replace('Z', '+00:00'))
                current_time = timezone.now()

                # 计算剩余秒数
                remaining_seconds = int((start_time - current_time).total_seconds())
                remaining_seconds = max(0, remaining_seconds)  # 确保不为负数

                # 如果倒计时已结束，清除转换信息
                if remaining_seconds <= 0:
                    worldcup.stage_transition_info = {}
                    worldcup.save()
                    is_transitioning = False

                return JsonResponse({
                    'status': 'success',
                    'data': {
                        'is_transitioning': is_transitioning,
                        'next_stage': stage_transition_info.get('next_stage', ''),
                        'remaining_seconds': remaining_seconds
                    }
                })
            else:
                # 如果没有开始时间，清除转换信息
                worldcup.stage_transition_info = {}
                worldcup.save()
                is_transitioning = False

        return JsonResponse({
            'status': 'success',
            'data': {
                'is_transitioning': is_transitioning,
                'next_stage': '',
                'remaining_seconds': 0
            }
        })

    except Exception as e:
        logger.error(f'获取阶段转换状态失败: {str(e)}')
        return JsonResponse({'error': '获取阶段转换状态失败'}, status=500)


@require_GET
@login_required
def api_worldcup_status(request, worldcup_id):
    """获取世界杯状态"""
    try:
        worldcup = get_object_or_404(WorldCup, id=worldcup_id)

        return JsonResponse({
            'status': 'success',
            'data': {
                'status': worldcup.status,
                'name': worldcup.name,
                'id': worldcup.id
            }
        })

    except Exception as e:
        logger.error(f'获取世界杯状态失败: {str(e)}')
        return JsonResponse({'error': '获取世界杯状态失败'}, status=500)


# ==================== Admin专用世界杯管理视图 ====================

@require_POST
@login_required
def admin_worldcup_confirm_participants(request, worldcup_id):
    """Admin专用：确定参赛名单"""
    if not request.user.is_staff:
        return JsonResponse({'error': '权限不足'}, status=403)

    try:
        worldcup = get_object_or_404(WorldCup, id=worldcup_id)

        if worldcup.status != 'preparing':
            return JsonResponse({'error': '世界杯状态不是准备中，无法确定参赛名单'}, status=400)

        from django.contrib.auth.models import User
        participants_created = 0

        # 检查是否有请求体数据（手动选择的参赛选手）
        try:
            data = json.loads(request.body) if request.body else {}
            selected_participants = data.get('participants', [])
        except json.JSONDecodeError:
            selected_participants = []

        if selected_participants:
            # 如果有手动选择的参赛选手，使用选中的列表
            errors = []

            for participant_data in selected_participants:
                try:
                    user_id = participant_data.get('user_id')
                    code_id = participant_data.get('code_id')

                    if not user_id or not code_id:
                        errors.append(f'参赛选手数据不完整')
                        continue

                    # 获取用户和代码
                    user = User.objects.get(id=user_id)
                    code = Code.objects.get(id=code_id, user=user)

                    # 检查是否已经参赛
                    if worldcup.participants.filter(user=user).exists():
                        errors.append(f'用户 {user.username} 已经参赛')
                        continue

                    # 创建参赛记录
                    WorldCupParticipant.objects.create(
                        worldcup=worldcup,
                        user=user,
                        code=code
                    )
                    participants_created += 1

                except User.DoesNotExist:
                    errors.append(f'用户不存在 (ID: {user_id})')
                except Code.DoesNotExist:
                    errors.append(f'代码不存在或不属于该用户 (Code ID: {code_id})')
                except Exception as e:
                    errors.append(f'处理参赛选手失败: {str(e)}')

            message = f'参赛名单已确定，共 {participants_created} 名新参赛者'
            if errors:
                message += f'，{len(errors)} 个错误'
        else:
            # 如果没有手动选择，检查是否已经有参赛选手
            existing_participants_count = worldcup.participants.count()

            if existing_participants_count > 0:
                # 如果已经有参赛选手，直接确认现有名单
                message = f'参赛名单已确定，确认现有 {existing_participants_count} 名参赛者'
            else:
                # 如果没有参赛选手，则使用所有有代码的用户（保持原有逻辑）
                users_with_codes = User.objects.filter(codes__isnull=False).distinct()

                for user in users_with_codes:
                    # 获取用户的第一份代码
                    first_code = user.codes.order_by('created_at').first()
                    if first_code:
                        # 检查是否已经参赛
                        if not worldcup.participants.filter(user=user).exists():
                            WorldCupParticipant.objects.create(
                                worldcup=worldcup,
                                user=user,
                                code=first_code
                            )
                            participants_created += 1

                message = f'参赛名单已确定，共 {participants_created} 名新参赛者'

        # 更新参赛人数和状态
        worldcup.total_participants = worldcup.participants.count()
        worldcup.status = 'ready'  # 确认名单后状态变为准备就绪
        worldcup.save()

        return JsonResponse({
            'success': True,
            'message': f'{message}，总参赛人数：{worldcup.total_participants}。世界杯现在准备就绪，可以开始常规赛！'
        })

    except Exception as e:
        logger.error(f'确定参赛名单失败: {str(e)}')
        return JsonResponse({'error': '确定参赛名单失败'}, status=500)


@require_POST
@login_required
def admin_worldcup_start_regular_season(request, worldcup_id):
    """Admin专用：开始常规赛"""
    if not request.user.is_staff:
        return JsonResponse({'error': '权限不足'}, status=403)

    try:
        worldcup = get_object_or_404(WorldCup, id=worldcup_id)

        total_matches = worldcup.start_regular_season()

        return JsonResponse({
            'success': True,
            'message': f'常规赛已开始，共创建 {total_matches} 场比赛'
        })

    except ValueError as e:
        return JsonResponse({'error': str(e)}, status=400)
    except Exception as e:
        logger.error(f'开始常规赛失败: {str(e)}')
        return JsonResponse({'error': '开始常规赛失败'}, status=500)


@require_POST
@login_required
def admin_worldcup_start_championship(request, worldcup_id):
    """Admin专用：开始冠军赛"""
    if not request.user.is_staff:
        return JsonResponse({'error': '权限不足'}, status=403)

    try:
        worldcup = get_object_or_404(WorldCup, id=worldcup_id)

        worldcup.start_championship()
        top_16_count = worldcup.participants.filter(stage='round_16', is_eliminated=False).count()

        return JsonResponse({
            'success': True,
            'message': f'冠军赛已开始，共 {top_16_count} 名参赛者进入16强'
        })

    except ValueError as e:
        return JsonResponse({'error': str(e)}, status=400)
    except Exception as e:
        logger.error(f'开始冠军赛失败: {str(e)}')
        return JsonResponse({'error': '开始冠军赛失败'}, status=500)


@require_POST
@login_required
def admin_worldcup_start_round16_grouping(request, worldcup_id):
    """Admin专用：16强分组准备"""
    if not request.user.is_staff:
        return JsonResponse({'error': '权限不足'}, status=403)

    try:
        worldcup = get_object_or_404(WorldCup, id=worldcup_id)

        # 检查世界杯状态
        if worldcup.status != 'regular_finished':
            return JsonResponse({'error': '只有常规赛完成后才能进行16强分组准备'}, status=400)

        # 调用16强分组准备方法
        worldcup.prepare_championship()
        top_16_count = worldcup.participants.filter(stage='round_16', is_eliminated=False).count()

        return JsonResponse({
            'success': True,
            'message': f'16强分组准备完成，共 {top_16_count} 名参赛者进入16强淘汰赛'
        })

    except ValueError as e:
        return JsonResponse({'error': str(e)}, status=400)
    except Exception as e:
        logger.error(f'16强分组准备失败: {str(e)}')
        return JsonResponse({'error': '16强分组准备失败'}, status=500)


@require_POST
@login_required
def admin_worldcup_check_progress(request, worldcup_id):
    """Admin专用：检查比赛进度"""
    if not request.user.is_staff:
        return JsonResponse({'error': '权限不足'}, status=403)

    try:
        worldcup = get_object_or_404(WorldCup, id=worldcup_id)

        if worldcup.status == 'regular_season':
            worldcup.check_regular_season_progress()
            total_matches = worldcup.total_regular_matches
            completed_matches = worldcup.completed_regular_matches
            progress = round((completed_matches / total_matches * 100) if total_matches > 0 else 0, 1)
            can_start_championship = worldcup.is_regular_season_complete()
            message = f'常规赛进度已更新：{completed_matches}/{total_matches}'

            # 获取各种状态的战斗数量
            battles = Battle.objects.filter(
                battle_type='worldcup_regular',
                worldcupmatch__worldcup=worldcup
            )

            running_battles = battles.filter(status='running').count()
            pending_battles = battles.filter(status='pending').count()
            finished_battles = battles.filter(status='finished').count()
            error_battles = battles.filter(status='error').count()

        elif worldcup.status == 'championship':
            # 检查冠军赛进度
            total_matches = worldcup.matches.filter(stage__in=['round_16', 'quarter_final', 'semi_final', 'final']).count()
            completed_matches = worldcup.matches.filter(
                stage__in=['round_16', 'quarter_final', 'semi_final', 'final'],
                is_completed=True
            ).count()
            progress = round((completed_matches / total_matches * 100) if total_matches > 0 else 0, 1)
            can_start_championship = False
            message = f'冠军赛进度：{completed_matches}/{total_matches}'

            # 获取冠军赛各种状态的战斗数量
            battles = Battle.objects.filter(
                battle_type='worldcup_championship',
                worldcupmatch__worldcup=worldcup
            )

            running_battles = battles.filter(status='running').count()
            pending_battles = battles.filter(status='pending').count()
            finished_battles = battles.filter(status='finished').count()
            error_battles = battles.filter(status='error').count()

        else:
            total_matches = 0
            completed_matches = 0
            progress = 0
            can_start_championship = False
            message = f'当前状态：{worldcup.get_status_display()}'
            running_battles = 0
            pending_battles = 0
            finished_battles = 0
            error_battles = 0

        return JsonResponse({
            'success': True,
            'message': message,
            'total_matches': total_matches,
            'completed_matches': completed_matches,
            'progress': progress,
            'can_start_championship': can_start_championship,
            'running_battles': running_battles,
            'pending_battles': pending_battles,
            'finished_battles': finished_battles,
            'error_battles': error_battles
        })

    except Exception as e:
        logger.error(f'检查比赛进度失败: {str(e)}')
        return JsonResponse({'error': '检查比赛进度失败'}, status=500)


@require_POST
@login_required
def admin_worldcup_force_end_regular_season(request, worldcup_id):
    """Admin专用：强制结束常规赛"""
    if not request.user.is_staff:
        return JsonResponse({'error': '权限不足'}, status=403)

    try:
        worldcup = get_object_or_404(WorldCup, id=worldcup_id)

        if worldcup.force_end_regular_season():
            return JsonResponse({
                'success': True,
                'message': f'世界杯 "{worldcup.name}" 常规赛已强制结束，已生成冠军赛16强名单'
            })

    except ValueError as e:
        return JsonResponse({'error': str(e)}, status=400)
    except Exception as e:
        logger.error(f'强制结束常规赛失败: {str(e)}')
        return JsonResponse({'error': '强制结束常规赛失败'}, status=500)


@require_GET
@login_required
def admin_worldcup_available_users(request, worldcup_id):
    """Admin专用：获取可用用户列表"""
    if not request.user.is_staff:
        return JsonResponse({'error': '权限不足'}, status=403)

    try:
        worldcup = get_object_or_404(WorldCup, id=worldcup_id)

        if worldcup.status != 'preparing':
            return JsonResponse({'error': '世界杯状态不是准备中，无法选择参赛选手'}, status=400)

        # 获取所有有代码的用户
        from django.contrib.auth.models import User
        users_with_codes = User.objects.filter(codes__isnull=False).distinct().order_by('username')

        users_data = []
        for user in users_with_codes:
            # 检查用户是否已经参赛
            is_participating = worldcup.participants.filter(user=user).exists()
            if not is_participating:
                # 获取用户的所有代码
                codes_data = []
                for code in user.codes.all().order_by('-created_at'):
                    codes_data.append({
                        'id': code.id,
                        'title': code.title,
                        'description': code.description or '',
                        'language': code.language,
                        'is_starred': code.is_starred,
                        'created_at': code.created_at.strftime('%Y-%m-%d %H:%M'),
                        'updated_at': code.updated_at.strftime('%Y-%m-%d %H:%M')
                    })

                if codes_data:  # 只包含有代码的用户
                    users_data.append({
                        'id': user.id,
                        'username': user.username,
                        'codes': codes_data
                    })

        return JsonResponse({
            'success': True,
            'users': users_data
        })

    except Exception as e:
        logger.error(f'获取可用用户列表失败: {str(e)}')
        return JsonResponse({'error': '获取可用用户列表失败'}, status=500)


@require_POST
@login_required
def admin_worldcup_manual_select_participants(request, worldcup_id):
    """Admin专用：手动选择参赛选手"""
    if not request.user.is_staff:
        return JsonResponse({'error': '权限不足'}, status=403)

    try:
        worldcup = get_object_or_404(WorldCup, id=worldcup_id)

        if worldcup.status != 'preparing':
            return JsonResponse({'error': '世界杯状态不是准备中，无法选择参赛选手'}, status=400)

        # 解析请求数据
        data = json.loads(request.body)
        participants = data.get('participants', [])

        if not participants:
            return JsonResponse({'error': '请至少选择一个参赛选手'}, status=400)

        # 验证和创建参赛记录
        from django.contrib.auth.models import User
        participants_created = 0
        errors = []

        for participant_data in participants:
            try:
                user_id = participant_data.get('user_id')
                code_id = participant_data.get('code_id')

                if not user_id or not code_id:
                    errors.append(f'参赛选手数据不完整')
                    continue

                # 获取用户和代码
                user = User.objects.get(id=user_id)
                code = Code.objects.get(id=code_id, user=user)

                # 检查是否已经参赛
                if worldcup.participants.filter(user=user).exists():
                    errors.append(f'用户 {user.username} 已经参赛')
                    continue

                # 创建参赛记录
                WorldCupParticipant.objects.create(
                    worldcup=worldcup,
                    user=user,
                    code=code
                )
                participants_created += 1

            except User.DoesNotExist:
                errors.append(f'用户不存在 (ID: {user_id})')
            except Code.DoesNotExist:
                errors.append(f'代码不存在或不属于该用户 (Code ID: {code_id})')
            except Exception as e:
                errors.append(f'处理参赛选手失败: {str(e)}')

        # 更新参赛人数
        worldcup.total_participants = worldcup.participants.count()
        worldcup.save()

        response_data = {
            'success': True,
            'message': f'成功添加 {participants_created} 名参赛选手，总参赛人数：{worldcup.total_participants}'
        }

        if errors:
            response_data['warnings'] = errors

        return JsonResponse(response_data)

    except json.JSONDecodeError:
        return JsonResponse({'error': '请求数据格式错误'}, status=400)
    except Exception as e:
        logger.error(f'手动选择参赛选手失败: {str(e)}')
        return JsonResponse({'error': '手动选择参赛选手失败'}, status=500)


@require_POST
@login_required
def admin_worldcup_remove_participant(request, worldcup_id, participant_id):
    """删除世界杯参赛选手"""
    if not request.user.is_staff:
        return JsonResponse({'error': '权限不足'}, status=403)

    try:
        worldcup = get_object_or_404(WorldCup, id=worldcup_id)

        # 只有在准备阶段才能删除参赛选手
        if worldcup.status != 'preparing':
            return JsonResponse({'error': '只能在准备阶段删除参赛选手'}, status=400)

        participant = get_object_or_404(WorldCupParticipant, id=participant_id, worldcup=worldcup)

        # 记录删除的参赛选手信息
        participant_info = {
            'username': participant.user.username,
            'code_title': participant.code.title if participant.code else '无代码'
        }

        # 删除参赛选手
        participant.delete()

        # 更新参赛人数
        worldcup.total_participants = worldcup.participants.count()
        worldcup.save()

        return JsonResponse({
            'success': True,
            'message': f'成功删除参赛选手 {participant_info["username"]}',
            'total_participants': worldcup.total_participants
        })

    except Exception as e:
        logger.error(f'删除参赛选手失败: {str(e)}')
        return JsonResponse({'error': '删除参赛选手失败'}, status=500)


@require_GET
@login_required
def api_worldcup_battle_queue_status(request, worldcup_id):
    """获取世界杯战斗队列状态"""
    if not request.user.is_staff:
        return JsonResponse({'error': '权限不足'}, status=403)

    try:
        from .battle_queue_manager import get_worldcup_battle_queue_status

        result = get_worldcup_battle_queue_status(worldcup_id)

        if result['success']:
            return JsonResponse(result)
        else:
            return JsonResponse({'error': result['error']}, status=400)

    except Exception as e:
        logger.error(f'获取战斗队列状态失败: {str(e)}')
        return JsonResponse({'error': '获取战斗队列状态失败'}, status=500)


@require_GET
@login_required
def api_worldcup_championship_queue_status(request, worldcup_id):
    """获取世界杯冠军赛队列状态"""
    if not request.user.is_staff:
        return JsonResponse({'error': '权限不足'}, status=403)

    try:
        from .battle_queue_manager import get_worldcup_championship_queue_status

        result = get_worldcup_championship_queue_status(worldcup_id)

        if result['success']:
            return JsonResponse(result)
        else:
            return JsonResponse({'error': result['error']}, status=400)

    except Exception as e:
        logger.error(f'获取冠军赛队列状态失败: {str(e)}')
        return JsonResponse({'error': '获取冠军赛队列状态失败'}, status=500)


@require_POST
@login_required
def api_worldcup_restart_battle_queue(request, worldcup_id):
    """重启世界杯冠军赛队列处理"""
    if not request.user.is_staff:
        return JsonResponse({'error': '权限不足'}, status=403)

    try:
        from .battle_queue_manager import restart_worldcup_championship_queue

        result = restart_worldcup_championship_queue(worldcup_id)

        if result['success']:
            return JsonResponse({
                'success': True,
                'message': result['message'],
                'details': result
            })
        else:
            return JsonResponse({'error': result['error']}, status=400)

    except Exception as e:
        logger.error(f'重启冠军赛队列失败: {str(e)}')
        return JsonResponse({'error': '重启冠军赛队列失败'}, status=500)


@require_POST
@login_required
def api_worldcup_stop_battle_queue(request, worldcup_id):
    """停止世界杯战斗队列处理"""
    if not request.user.is_staff:
        return JsonResponse({'error': '权限不足'}, status=403)

    try:
        from .battle_queue_manager import get_battle_queue_manager

        queue_manager = get_battle_queue_manager()
        queue_manager.stop_processing()

        return JsonResponse({
            'success': True,
            'message': '战斗队列处理已停止'
        })

    except Exception as e:
        logger.error(f'停止战斗队列失败: {str(e)}')
        return JsonResponse({'error': '停止战斗队列失败'}, status=500)


@require_POST
@login_required
def admin_worldcup_rerun_error_battles(request, worldcup_id):
    """重新运行世界杯错误战斗"""
    if not request.user.is_staff:
        return JsonResponse({'error': '权限不足'}, status=403)

    try:
        worldcup = get_object_or_404(WorldCup, id=worldcup_id)

        # 获取所有错误的常规赛战斗
        error_matches = worldcup.matches.filter(
            stage='regular',
            battle__status='error'
        ).select_related('battle')

        error_count = error_matches.count()

        if error_count == 0:
            return JsonResponse({
                'success': True,
                'message': '没有发现错误战斗',
                'rerun_count': 0
            })

        # 重新运行错误战斗
        rerun_count = 0
        failed_count = 0

        for match in error_matches:
            try:
                # 重置战斗状态
                battle = match.battle
                battle.status = 'pending'
                battle.result = None
                battle.error_message = ''
                battle.finished_at = None
                battle.save()

                # 删除旧的回合数据
                battle.rounds.all().delete()

                # 将战斗加入队列等待执行
                from .battle_queue_manager import get_battle_queue_manager
                queue_manager = get_battle_queue_manager()
                queue_manager.add_battles_to_queue([battle.id])

                rerun_count += 1
                logger.info(f'重新运行错误战斗: {battle.id}')

            except Exception as e:
                failed_count += 1
                logger.error(f'重新运行战斗 {match.battle.id} 失败: {str(e)}')

        return JsonResponse({
            'success': True,
            'message': f'成功重新运行 {rerun_count} 个错误战斗',
            'rerun_count': rerun_count,
            'failed_count': failed_count,
            'total_error_count': error_count
        })

    except Exception as e:
        logger.error(f'重新运行错误战斗失败: {str(e)}')
        return JsonResponse({'error': f'重新运行错误战斗失败: {str(e)}'}, status=500)


@require_POST
@login_required
def admin_worldcup_requeue_error_pending_battles(request, worldcup_id):
    """将错误和等待状态的战斗重新加入常规赛队列"""
    if not request.user.is_staff:
        return JsonResponse({'error': '权限不足'}, status=403)

    try:
        worldcup = get_object_or_404(WorldCup, id=worldcup_id)

        # 获取所有错误和等待状态的常规赛战斗
        error_pending_matches = worldcup.matches.filter(
            stage='regular',
            battle__status__in=['error', 'pending']
        ).select_related('battle')

        total_count = error_pending_matches.count()

        if total_count == 0:
            return JsonResponse({
                'success': True,
                'message': '没有发现错误或等待状态的战斗',
                'requeue_count': 0
            })

        # 获取队列管理器
        from .battle_queue_manager import get_battle_queue_manager
        queue_manager = get_battle_queue_manager()

        # 获取当前队列中的战斗ID，防止重复
        current_queue_status = queue_manager.get_queue_status()
        current_pending_battles = set(queue_manager.pending_battles)
        current_running_battles = queue_manager.running_battles

        # 重新加入队列
        requeue_count = 0
        skipped_count = 0
        failed_count = 0

        for match in error_pending_matches:
            try:
                battle = match.battle
                battle_id = battle.id

                # 检查是否已在队列中，防止重复
                if battle_id in current_pending_battles or battle_id in current_running_battles:
                    skipped_count += 1
                    logger.info(f'战斗 {battle_id} 已在队列中，跳过')
                    continue

                # 如果是错误状态，重置战斗状态
                if battle.status == 'error':
                    battle.status = 'pending'
                    battle.result = None
                    battle.error_message = ''
                    battle.finished_at = None
                    battle.save()

                    # 删除旧的回合数据
                    battle.rounds.all().delete()

                # 将战斗加入队列等待执行
                queue_manager.add_battles_to_queue([battle_id])

                requeue_count += 1
                logger.info(f'重新加入队列: 战斗 {battle_id} (状态: {battle.status})')

            except Exception as e:
                failed_count += 1
                logger.error(f'重新加入队列失败，战斗 {match.battle.id}: {str(e)}')

        return JsonResponse({
            'success': True,
            'message': f'成功将 {requeue_count} 个战斗重新加入队列',
            'requeue_count': requeue_count,
            'skipped_count': skipped_count,
            'failed_count': failed_count,
            'total_count': total_count
        })

    except Exception as e:
        logger.error(f'重新加入队列失败: {str(e)}')
        return JsonResponse({'error': f'重新加入队列失败: {str(e)}'}, status=500)


@csrf_exempt
@require_POST
@login_required
def admin_worldcup_rerun_championship_error_battles(request, worldcup_id):
    """重新运行世界杯冠军赛错误战斗"""
    if not request.user.is_staff:
        return JsonResponse({'error': '权限不足'}, status=403)

    try:
        worldcup = get_object_or_404(WorldCup, id=worldcup_id)

        # 获取所有错误的冠军赛战斗（淘汰赛阶段）
        error_matches = worldcup.matches.filter(
            stage__in=['round_16', 'quarter_final', 'semi_final', 'final'],
            battle__status='error'
        ).select_related('battle')

        error_count = error_matches.count()

        if error_count == 0:
            return JsonResponse({
                'success': True,
                'message': '没有发现冠军赛错误战斗',
                'rerun_count': 0
            })

        # 重新运行错误战斗
        rerun_count = 0
        failed_count = 0

        for match in error_matches:
            try:
                # 重置战斗状态
                battle = match.battle
                battle.status = 'pending'
                battle.result = None
                battle.error_message = ''
                battle.finished_at = None
                battle.save()

                # 删除旧的回合数据
                battle.rounds.all().delete()

                # 将战斗加入冠军赛队列等待执行
                from .battle_queue_manager import get_battle_queue_manager
                queue_manager = get_battle_queue_manager()
                queue_manager.add_battles_to_queue([battle.id])

                rerun_count += 1
                logger.info(f'重新运行冠军赛错误战斗: {battle.id}')

            except Exception as e:
                failed_count += 1
                logger.error(f'重新运行冠军赛战斗 {match.battle.id} 失败: {str(e)}')

        return JsonResponse({
            'success': True,
            'message': f'成功重新运行 {rerun_count} 个冠军赛错误战斗',
            'rerun_count': rerun_count,
            'failed_count': failed_count,
            'total_error_count': error_count
        })

    except Exception as e:
        logger.error(f'重新运行冠军赛错误战斗失败: {str(e)}')
        return JsonResponse({'error': f'重新运行冠军赛错误战斗失败: {str(e)}'}, status=500)


@csrf_exempt
@require_POST
@login_required
def admin_worldcup_requeue_championship_error_pending_battles(request, worldcup_id):
    """将错误和等待状态的冠军赛战斗重新加入队列"""
    if not request.user.is_staff:
        return JsonResponse({'error': '权限不足'}, status=403)

    try:
        worldcup = get_object_or_404(WorldCup, id=worldcup_id)

        # 获取所有错误和等待状态的冠军赛战斗（淘汰赛阶段）
        error_pending_matches = worldcup.matches.filter(
            stage__in=['round_16', 'quarter_final', 'semi_final', 'final'],
            battle__status__in=['error', 'pending']
        ).select_related('battle')

        total_count = error_pending_matches.count()

        if total_count == 0:
            return JsonResponse({
                'success': True,
                'message': '没有发现冠军赛错误或等待状态的战斗',
                'requeue_count': 0
            })

        # 获取队列管理器
        from .battle_queue_manager import get_battle_queue_manager
        queue_manager = get_battle_queue_manager()

        # 获取当前队列中的战斗ID，防止重复
        current_queue_status = queue_manager.get_queue_status()
        current_pending_battles = set(queue_manager.pending_battles)
        current_running_battles = queue_manager.running_battles

        # 重新加入队列
        requeue_count = 0
        skipped_count = 0
        failed_count = 0

        for match in error_pending_matches:
            try:
                battle = match.battle
                battle_id = battle.id

                # 检查是否已在队列中，防止重复
                if battle_id in current_pending_battles or battle_id in current_running_battles:
                    skipped_count += 1
                    logger.info(f'冠军赛战斗 {battle_id} 已在队列中，跳过')
                    continue

                # 如果是错误状态，重置战斗状态
                if battle.status == 'error':
                    battle.status = 'pending'
                    battle.result = None
                    battle.error_message = ''
                    battle.finished_at = None
                    battle.save()

                    # 删除旧的回合数据
                    battle.rounds.all().delete()

                # 将战斗加入队列等待执行
                queue_manager.add_battles_to_queue([battle_id])

                requeue_count += 1
                logger.info(f'重新加入冠军赛队列: 战斗 {battle_id} (状态: {battle.status})')

            except Exception as e:
                failed_count += 1
                logger.error(f'重新加入冠军赛队列失败，战斗 {match.battle.id}: {str(e)}')

        return JsonResponse({
            'success': True,
            'message': f'成功将 {requeue_count} 个冠军赛战斗重新加入队列',
            'requeue_count': requeue_count,
            'skipped_count': skipped_count,
            'failed_count': failed_count,
            'total_count': total_count
        })

    except Exception as e:
        logger.error(f'重新加入冠军赛队列失败: {str(e)}')
        return JsonResponse({'error': f'重新加入冠军赛队列失败: {str(e)}'}, status=500)


@require_POST
@login_required
def admin_worldcup_start_championship_queue(request, worldcup_id):
    """手动启动冠军赛队列"""
    try:
        # 检查用户权限
        if not request.user.is_staff:
            return JsonResponse({'error': '权限不足'}, status=403)

        worldcup = get_object_or_404(WorldCup, id=worldcup_id)

        # 检查世界杯状态
        if worldcup.status != 'championship':
            return JsonResponse({
                'success': False,
                'error': '世界杯不在冠军赛阶段'
            })

        # 导入队列管理器函数
        from .battle_queue_manager import start_worldcup_championship_battles

        # 启动冠军赛队列
        result = start_worldcup_championship_battles(worldcup_id)

        if result.get('success'):
            logger.info(f'管理员 {request.user.username} 手动启动了世界杯 {worldcup_id} 的冠军赛队列')
            return JsonResponse({
                'success': True,
                'message': '冠军赛队列启动成功'
            })
        else:
            return JsonResponse({
                'success': False,
                'error': result.get('error', '启动冠军赛队列失败')
            })

    except Exception as e:
        logger.error(f'启动冠军赛队列失败: {str(e)}')
        return JsonResponse({
            'success': False,
            'error': f'启动冠军赛队列失败: {str(e)}'
        }, status=500)


@require_GET
@login_required
def api_worldcup_ongoing_battles(request, worldcup_id):
    """API: 获取世界杯正在进行中的战斗"""
    try:
        worldcup = get_object_or_404(WorldCup, id=worldcup_id)

        # 获取正在进行中的战斗（running 和 pending 状态）
        ongoing_battles = Battle.objects.filter(
            Q(battle_type='worldcup_regular') | Q(battle_type='worldcup_championship'),
            worldcupmatch__worldcup=worldcup,
            status__in=['running', 'pending']
        ).order_by('-created_at')

        battles_data = []
        for battle in ongoing_battles:
            # 计算战斗进度 - 从game_config或worldcup中获取round_limit
            total_rounds = 100  # 默认值
            if battle.game_config:
                game_config = battle.game_config if isinstance(battle.game_config, dict) else {}
                total_rounds = game_config.get('round_limit', 100)
            elif hasattr(battle, 'worldcupmatch') and battle.worldcupmatch.worldcup:
                total_rounds = battle.worldcupmatch.worldcup.round_limit

            current_round = battle.rounds.count()
            progress_percentage = min(int((current_round / total_rounds) * 100), 100) if total_rounds > 0 else 0

            battles_data.append({
                'id': battle.id,
                'status': battle.status,
                'player1': battle.player1.username if battle.player1 else None,
                'player2': battle.player2.username if battle.player2 else None,
                'battle_type': battle.battle_type,
                'created_at': battle.created_at.isoformat(),
                'current_round': current_round,
                'total_rounds': total_rounds,
                'progress_percentage': progress_percentage,
            })

        return JsonResponse({
            'status': 'success',
            'data': battles_data
        })

    except Exception as e:
        logger.error(f'获取正在进行中的战斗失败: {str(e)}')
        return JsonResponse({'error': '获取数据失败'}, status=500)


@login_required
def monitoring_dashboard(request):
    """监控仪表板页面"""
    return render(request, 'battles/monitoring_dashboard.html')


@require_GET
@login_required
def api_monitoring_metrics(request):
    """API: 获取监控指标数据"""
    try:
        from .monitoring import get_battle_monitor
        monitor = get_battle_monitor()

        # 获取系统指标
        system_metrics = monitor.get_system_metrics()

        # 获取最近的告警
        recent_alerts = monitor.get_recent_alerts(limit=10)

        # 转换告警格式
        alerts_data = []
        for alert in recent_alerts:
            alerts_data.append({
                'timestamp': alert.timestamp.isoformat(),
                'type': alert.alert_type.value,
                'level': alert.level.value,
                'message': alert.message,
                'battle_id': alert.battle_id,
                'metadata': alert.metadata
            })

        # 获取服务器状态
        server_manager = get_node_server_manager()
        servers_status = []

        for battle_id, server in server_manager.servers.items():
            # 获取服务器详细状态信息
            server_status = server.get_status()

            status = {
                'battle_id': battle_id,
                'port': server.port,
                'is_healthy': server.is_healthy(),
                'cpu_percent': 0,
                'memory_mb': 0,
                'pid': None,
                'player1_name': None,
                'player2_name': None,
                'duration_seconds': server_status.get('uptime', 0)  # 添加持续时间
            }

            # 获取进程信息
            try:
                if server.process and server.process.poll() is None:
                    import psutil
                    proc = psutil.Process(server.process.pid)
                    # 使用interval参数获取准确的CPU使用率
                    # 第一次调用cpu_percent()会返回0.0，所以我们使用interval=1秒来获取实际值
                    status['cpu_percent'] = proc.cpu_percent(interval=1)
                    status['memory_mb'] = proc.memory_info().rss / 1024 / 1024
                    status['pid'] = server.process.pid
            except:
                pass

            # 获取对战双方名字和回合信息
            try:
                battle = Battle.objects.get(id=battle_id)
                status['player1_name'] = battle.player1.username if battle.player1 else None
                status['player2_name'] = battle.player2.username if battle.player2 else None

                # 添加回合信息
                status['current_round'] = battle.rounds.count()  # 当前已完成的回合数

                # 使用实际的回合限制：优先使用battle.total_rounds，如果为0则从game_config获取，最后才使用默认值
                if battle.total_rounds > 0:
                    # 战斗已完成，使用实际执行的回合数
                    status['total_rounds'] = battle.total_rounds
                elif battle.game_config:
                    # 战斗进行中，从game_config获取回合限制
                    try:
                        game_config = json.loads(battle.game_config) if isinstance(battle.game_config, str) else battle.game_config
                        status['total_rounds'] = game_config.get('round_limit', settings.BATTLE_ENGINE.get('MAX_ROUNDS', 200))
                    except (json.JSONDecodeError, TypeError):
                        status['total_rounds'] = settings.BATTLE_ENGINE.get('MAX_ROUNDS', 200)
                else:
                    # 使用默认值
                    status['total_rounds'] = settings.BATTLE_ENGINE.get('MAX_ROUNDS', 200)

                status['round_progress'] = f"{status['current_round']}/{status['total_rounds']}"  # 回合进度显示

            except Battle.DoesNotExist:
                # 如果找不到对战记录，保持默认值None
                pass
            except Exception as e:
                logger.debug(f'获取对战信息失败 {battle_id}: {e}')

            servers_status.append(status)

        return JsonResponse({
            'status': 'success',
            'data': {
                'metrics': system_metrics,
                'recent_alerts': alerts_data,
                'servers_status': servers_status,
                'timestamp': timezone.now().isoformat()
            }
        })

    except Exception as e:
        logger.error(f'获取监控指标失败: {str(e)}')
        return JsonResponse({'error': '获取监控数据失败'}, status=500)


@require_GET
@login_required
def api_monitoring_alerts(request):
    """API: 获取告警历史"""
    try:
        from .monitoring import get_battle_monitor
        monitor = get_battle_monitor()

        # 获取查询参数
        limit = int(request.GET.get('limit', 50))
        alert_type = request.GET.get('type')
        alert_level = request.GET.get('level')

        # 获取告警历史
        alerts = monitor.get_alerts_history(hours=24)  # 获取24小时内的告警

        # 过滤告警
        if alert_type:
            alerts = [a for a in alerts if a.type.value == alert_type]
        if alert_level:
            alerts = [a for a in alerts if a.level.value == alert_level]

        # 限制数量
        alerts = alerts[:limit]

        # 转换格式
        alerts_data = []
        for alert in alerts:
            alerts_data.append({
                'id': getattr(alert, 'id', str(hash(alert.message + str(alert.timestamp)))),
                'timestamp': alert.timestamp.isoformat(),
                'type': alert.alert_type.value,
                'level': alert.level.value,
                'message': alert.message,
                'battle_id': alert.battle_id,
                'metadata': alert.metadata
            })

        return JsonResponse({
            'status': 'success',
            'data': alerts_data
        })

    except Exception as e:
        logger.error(f'获取告警历史失败: {str(e)}')
        return JsonResponse({'error': '获取告警数据失败'}, status=500)


@require_POST
@login_required
def api_monitoring_clear_alerts(request):
    """API: 清除告警"""
    try:
        from .monitoring import get_battle_monitor
        monitor = get_battle_monitor()

        data = json.loads(request.body)
        alert_ids = data.get('alert_ids', [])

        if alert_ids:
            monitor.clear_alerts(alert_ids)
        else:
            monitor.clear_all_alerts()

        return JsonResponse({
            'status': 'success',
            'message': '告警已清除'
        })

    except Exception as e:
        logger.error(f'清除告警失败: {str(e)}')
        return JsonResponse({'error': '清除告警失败'}, status=500)


@csrf_exempt
@require_POST
@login_required
def api_monitoring_generate_test_alerts(request):
    """API: 生成测试告警"""
    try:
        from .monitoring import get_battle_monitor, AlertType, AlertLevel
        monitor = get_battle_monitor()

        # 生成几个不同类型的测试告警
        test_alerts = [
            {
                'type': AlertType.HIGH_MEMORY_USAGE,
                'level': AlertLevel.WARNING,
                'message': '测试告警：内存使用率过高 (85%)',
                'battle_id': 'test_001',
                'metadata': {'memory_percent': 85, 'threshold': 80}
            },
            {
                'type': AlertType.STATE_INCONSISTENCY,
                'level': AlertLevel.ERROR,
                'message': '测试告警：状态不一致检测',
                'battle_id': 'test_002',
                'metadata': {'expected_state': 'running', 'actual_state': 'error'}
            },
            {
                'type': AlertType.SERVER_UNHEALTHY,
                'level': AlertLevel.CRITICAL,
                'message': '测试告警：服务器健康检查失败',
                'battle_id': 'test_003',
                'metadata': {'port': 8001, 'error': 'Connection refused'}
            }
        ]

        # 添加告警到监控器
        for alert_data in test_alerts:
            monitor.send_manual_alert(
                alert_type=alert_data['type'],
                level=alert_data['level'],
                message=alert_data['message'],
                battle_id=alert_data['battle_id'],
                metadata=alert_data['metadata']
            )

        return JsonResponse({
            'status': 'success',
            'message': f'已生成 {len(test_alerts)} 个测试告警',
            'alerts_generated': len(test_alerts)
        })

    except Exception as e:
        logger.error(f'生成测试告警失败: {str(e)}')
        return JsonResponse({'error': '生成测试告警失败'}, status=500)


# 管理员战斗操作相关视图
@csrf_exempt
@require_POST
@login_required
def admin_battle_delete(request, battle_id):
    """删除战斗"""
    if not request.user.is_staff:
        return JsonResponse({'error': '权限不足'}, status=403)

    try:
        battle = get_object_or_404(Battle, id=battle_id)
        battle_id_str = str(battle.id)
        battle.delete()

        logger.info(f'管理员 {request.user.username} 删除了战斗 {battle_id_str}')
        return JsonResponse({
            'status': 'success',
            'message': f'战斗 {battle_id_str} 已删除'
        })
    except Exception as e:
        logger.error(f'删除战斗失败: {str(e)}')
        return JsonResponse({'error': '删除战斗失败'}, status=500)


@csrf_exempt
@require_POST
@login_required
def admin_battle_mark_exciting(request, battle_id):
    """标记战斗为精彩"""
    if not request.user.is_staff:
        return JsonResponse({'error': '权限不足'}, status=403)

    try:
        battle = get_object_or_404(Battle, id=battle_id)
        battle.is_exciting = True
        battle.is_manually_marked = True
        battle.save()

        logger.info(f'管理员 {request.user.username} 将战斗 {battle_id} 标记为精彩')
        return JsonResponse({
            'status': 'success',
            'message': f'战斗 {battle_id} 已标记为精彩'
        })
    except Exception as e:
        logger.error(f'标记精彩战斗失败: {str(e)}')
        return JsonResponse({'error': '标记精彩战斗失败'}, status=500)


@csrf_exempt
@require_POST
@login_required
def admin_battle_unmark_exciting(request, battle_id):
    """取消精彩战斗标记"""
    if not request.user.is_staff:
        return JsonResponse({'error': '权限不足'}, status=403)

    try:
        battle = get_object_or_404(Battle, id=battle_id)
        battle.is_exciting = False
        battle.is_manually_marked = False
        battle.save()

        logger.info(f'管理员 {request.user.username} 取消了战斗 {battle_id} 的精彩标记')
        return JsonResponse({
            'status': 'success',
            'message': f'战斗 {battle_id} 已取消精彩标记'
        })
    except Exception as e:
        logger.error(f'取消精彩战斗标记失败: {str(e)}')
        return JsonResponse({'error': '取消精彩战斗标记失败'}, status=500)


@csrf_exempt
@require_POST
@login_required
def admin_battle_batch_operation(request):
    """批量操作战斗"""
    if not request.user.is_staff:
        return JsonResponse({'error': '权限不足'}, status=403)

    try:
        data = json.loads(request.body)
        battle_ids = data.get('battle_ids', [])
        operation = data.get('operation')

        if not battle_ids:
            return JsonResponse({'error': '未选择任何战斗'}, status=400)

        if operation not in ['delete', 'mark_exciting', 'unmark_exciting']:
            return JsonResponse({'error': '无效的操作类型'}, status=400)

        battles = Battle.objects.filter(id__in=battle_ids)
        success_count = 0

        for battle in battles:
            try:
                if operation == 'delete':
                    battle.delete()
                elif operation == 'mark_exciting':
                    battle.is_exciting = True
                    battle.is_manually_marked = True
                    battle.save()
                elif operation == 'unmark_exciting':
                    battle.is_exciting = False
                    battle.is_manually_marked = False
                    battle.save()
                success_count += 1
            except Exception as e:
                logger.error(f'批量操作战斗 {battle.id} 失败: {str(e)}')
                continue

        operation_names = {
            'delete': '删除',
            'mark_exciting': '标记为精彩',
            'unmark_exciting': '取消精彩标记'
        }

        logger.info(f'管理员 {request.user.username} 批量{operation_names[operation]}了 {success_count} 场战斗')
        return JsonResponse({
            'status': 'success',
            'message': f'成功{operation_names[operation]} {success_count} 场战斗',
            'success_count': success_count,
            'total_count': len(battle_ids)
        })

    except json.JSONDecodeError:
        return JsonResponse({'error': '无效的JSON数据'}, status=400)
    except Exception as e:
        logger.error(f'批量操作失败: {str(e)}')
        return JsonResponse({'error': '批量操作失败'}, status=500)


@require_POST
@login_required
def admin_worldcup_advance_next_stage(request, worldcup_id):
    """Admin专用：手动推进到下一阶段"""
    if not request.user.is_staff:
        return JsonResponse({'error': '权限不足'}, status=403)

    try:
        worldcup = get_object_or_404(WorldCup, id=worldcup_id)

        # 检查世界杯状态
        if worldcup.status != 'championship':
            return JsonResponse({'error': '只有冠军赛阶段才能手动推进下一阶段'}, status=400)

        # 获取当前阶段的所有比赛
        stages = ['round_16', 'quarter_final', 'semi_final', 'final']
        current_stage = None

        # 找到当前进行中的阶段
        for stage in stages:
            stage_matches = WorldCupMatch.objects.filter(
                worldcup=worldcup,
                stage=stage
            )

            if stage_matches.exists():
                completed_matches = stage_matches.filter(is_completed=True).count()
                total_matches = stage_matches.count()

                # 如果这个阶段有未完成的比赛，说明这是当前阶段
                if completed_matches < total_matches:
                    current_stage = stage
                    break
                # 如果这个阶段全部完成，但是下一阶段还没有比赛，说明需要推进
                elif completed_matches == total_matches:
                    next_stage_index = stages.index(stage) + 1
                    if next_stage_index < len(stages):
                        next_stage = stages[next_stage_index]
                        next_stage_matches = WorldCupMatch.objects.filter(
                            worldcup=worldcup,
                            stage=next_stage
                        )
                        if not next_stage_matches.exists():
                            current_stage = stage
                            break

        if not current_stage:
            return JsonResponse({'error': '无法确定当前阶段或冠军赛已结束'}, status=400)

        # 检查当前阶段是否全部完成
        current_stage_matches = WorldCupMatch.objects.filter(
            worldcup=worldcup,
            stage=current_stage
        )

        completed_matches = current_stage_matches.filter(is_completed=True).count()
        total_matches = current_stage_matches.count()

        # 初始化强制完成的战斗计数器
        battles_marked_complete = 0

        if completed_matches < total_matches:
            # 手动推进：强制将所有未完成的战斗标记为已完成
            from django.utils import timezone

            incomplete_matches = current_stage_matches.filter(is_completed=False)

            for match in incomplete_matches:
                if match.battle and match.battle.status != 'finished':
                    # 强制标记战斗为已完成，结果为平局
                    match.battle.status = 'finished'
                    match.battle.result = 'draw'
                    match.battle.finished_at = timezone.now()
                    match.battle.save()
                    battles_marked_complete += 1

                # 标记比赛为已完成
                if not match.is_completed:
                    match.is_completed = True
                    match.completed_at = timezone.now()
                    # 如果战斗结果是平局，winner保持为None
                    match.save()

            # 记录操作日志
            import logging
            logger = logging.getLogger(__name__)
            logger.info(f"手动推进世界杯 {worldcup.name} 下一阶段：强制完成了 {battles_marked_complete} 场战斗和 {incomplete_matches.count()} 场比赛")

        # 手动触发下一阶段创建
        # 获取一个已完成的比赛来触发检查
        completed_match = current_stage_matches.filter(is_completed=True).first()
        if completed_match:
            # 调用检查和创建下一轮的方法
            completed_match._check_and_create_next_round()

            # 确定推进到的阶段
            current_stage_index = stages.index(current_stage)
            if current_stage_index + 1 < len(stages):
                next_stage = stages[current_stage_index + 1]
                stage_names = {
                    'round_16': '16强',
                    'quarter_final': '8强',
                    'semi_final': '4强',
                    'final': '决赛'
                }

                # 构建成功消息，包含强制完成的战斗信息
                message = f'成功推进到下一阶段：{stage_names.get(next_stage, next_stage)}'
                if battles_marked_complete > 0:
                    message += f'（强制完成了 {battles_marked_complete} 场未完成的战斗）'

                return JsonResponse({
                    'success': True,
                    'message': message
                })
            else:
                # 构建成功消息，包含强制完成的战斗信息
                message = '冠军赛已全部完成，正在设置最终排名'
                if battles_marked_complete > 0:
                    message += f'（强制完成了 {battles_marked_complete} 场未完成的战斗）'

                return JsonResponse({
                    'success': True,
                    'message': message
                })
        else:
            return JsonResponse({'error': '找不到已完成的比赛来触发推进'}, status=400)

    except Exception as e:
        logger.error(f'手动推进下一阶段失败: {str(e)}')
        return JsonResponse({'error': f'推进失败: {str(e)}'}, status=500)


@login_required
def worldcup_special_rankings(request, worldcup_id):
    """世界杯特色排行榜页面"""
    worldcup = get_object_or_404(WorldCup, id=worldcup_id)

    # 获取该世界杯的所有常规赛比赛
    regular_matches = WorldCupMatch.objects.filter(
        worldcup=worldcup,
        stage='regular',
        is_completed=True,
        battle__isnull=False
    )

    # 获取所有参赛者
    participants = WorldCupParticipant.objects.filter(worldcup=worldcup)

    # 初始化统计数据
    healing_rankings = []
    death_rankings = []
    destroyed_rankings = []

    for participant in participants:
        user = participant.user

        # 获取该用户在常规赛中的所有对战
        user_matches = regular_matches.filter(
            Q(participant1=participant) | Q(participant2=participant)
        )

        total_healing = 0
        total_deaths = 0
        base_destroyed_count = 0
        regular_matches_played = 0

        for match in user_matches:
            battle = match.battle
            if not battle or battle.status != 'finished':
                continue

            regular_matches_played += 1

            # 获取用户在该对战中的统计数据
            if battle.player1 == user:
                # 用户是player1
                player_stats = battle.player1_stats or {}
                base_health = player_stats.get('baseHealth', 100)
                stats = player_stats.get('stats', {})
            else:
                # 用户是player2
                player_stats = battle.player2_stats or {}
                base_health = player_stats.get('baseHealth', 100)
                stats = player_stats.get('stats', {})

            # 累计治疗量
            total_healing += stats.get('totalHealing', 0)

            # 累计死亡数
            total_deaths += stats.get('deaths', 0)

            # 检查基地是否被摧毁（血量为0）
            if base_health <= 0:
                base_destroyed_count += 1

        # 计算平均值
        avg_healing = total_healing / regular_matches_played if regular_matches_played > 0 else 0
        avg_deaths = total_deaths / regular_matches_played if regular_matches_played > 0 else 0
        destroyed_rate = (base_destroyed_count / regular_matches_played * 100) if regular_matches_played > 0 else 0

        # 添加到统计列表（只有参与过比赛的才显示）
        if regular_matches_played > 0:
            healing_rankings.append({
                'participant': participant,
                'total_healing': total_healing,
                'regular_matches_played': regular_matches_played,
                'avg_healing': avg_healing
            })

            death_rankings.append({
                'participant': participant,
                'total_deaths': total_deaths,
                'regular_matches_played': regular_matches_played,
                'avg_deaths': avg_deaths
            })

            destroyed_rankings.append({
                'participant': participant,
                'base_destroyed_count': base_destroyed_count,
                'regular_matches_played': regular_matches_played,
                'destroyed_rate': destroyed_rate
            })

    # 排序
    healing_rankings.sort(key=lambda x: x['total_healing'], reverse=True)
    death_rankings.sort(key=lambda x: x['total_deaths'], reverse=True)
    destroyed_rankings.sort(key=lambda x: x['base_destroyed_count'], reverse=True)

    return render(request, 'battles/worldcup_special_rankings.html', {
        'worldcup': worldcup,
        'healing_rankings': healing_rankings,
        'death_rankings': death_rankings,
        'destroyed_rankings': destroyed_rankings,
    })


@require_POST
@login_required
def api_worldcup_auto_requeue_battles(request, worldcup_id):
    """自动检测并重新加入错误和等待中的战斗到队列

    当战斗队列正在启动状态且待处理和运行中数量都为0时，
    且数据库中有错误战斗和等待中战斗大于0时，
    则自动把这部分战斗重新加到战斗队列管理的待处理队列中
    """
    try:
        worldcup = get_object_or_404(WorldCup, id=worldcup_id)

        # 检查用户权限
        if not request.user.is_staff:
            return JsonResponse({
                'success': False,
                'error': '权限不足'
            }, status=403)

        from .battle_queue_manager import get_worldcup_battle_queue_status

        # 获取队列状态
        queue_status = get_worldcup_battle_queue_status(worldcup_id)

        # 检查队列是否正在处理
        if not queue_status.get('is_processing', False):
            return JsonResponse({
                'success': False,
                'error': '队列未启动，无需自动重新加入战斗',
                'queue_status': queue_status
            })

        # 检查待处理和运行中的战斗数量
        pending_count = queue_status.get('pending_battles', 0)
        running_count = queue_status.get('running_battles', 0)

        if pending_count > 0 or running_count > 0:
            return JsonResponse({
                'success': False,
                'error': f'队列中仍有战斗在处理中（待处理: {pending_count}, 运行中: {running_count}），无需自动重新加入',
                'queue_status': queue_status
            })

        # 获取错误和等待中的战斗
        error_battles = Battle.objects.filter(
            worldcup_match__worldcup=worldcup,
            worldcup_match__stage='regular',
            status='error'
        )

        pending_battles = Battle.objects.filter(
            worldcup_match__worldcup=worldcup,
            worldcup_match__stage='regular',
            status='pending'
        )

        error_count = error_battles.count()
        pending_count_db = pending_battles.count()

        if error_count == 0 and pending_count_db == 0:
            return JsonResponse({
                'success': False,
                'error': '数据库中没有错误或等待中的战斗，无需重新加入',
                'queue_status': queue_status
            })

        # 获取队列管理器
        from .battle_queue_manager import get_battle_queue_manager
        queue_manager = get_battle_queue_manager()

        # 检查队列中已存在的战斗，避免重复
        existing_battle_ids = set()
        try:
            with queue_manager.queue_lock:
                existing_battle_ids = {item.battle_id for item in queue_manager.battle_queue}
        except Exception as e:
            logger.warning(f"获取队列中现有战斗ID时出错: {e}")

        requeued_battles = []

        # 处理错误战斗
        for battle in error_battles:
            if battle.id not in existing_battle_ids:
                # 重置状态为pending
                battle.status = 'pending'
                battle.save()

                # 删除旧的回合数据
                battle.battleround_set.all().delete()

                # 添加到队列
                queue_manager.add_battle(battle.id)
                requeued_battles.append({
                    'id': battle.id,
                    'type': 'error',
                    'player1': battle.player1.username if battle.player1 else 'Unknown',
                    'player2': battle.player2.username if battle.player2 else 'Unknown'
                })

        # 处理等待中战斗
        for battle in pending_battles:
            if battle.id not in existing_battle_ids:
                # 添加到队列
                queue_manager.add_battle(battle.id)
                requeued_battles.append({
                    'id': battle.id,
                    'type': 'pending',
                    'player1': battle.player1.username if battle.player1 else 'Unknown',
                    'player2': battle.player2.username if battle.player2 else 'Unknown'
                })

        # 获取更新后的队列状态
        updated_queue_status = get_worldcup_battle_queue_status(worldcup_id)

        return JsonResponse({
            'success': True,
            'message': f'成功自动重新加入 {len(requeued_battles)} 场战斗到队列',
            'requeued_count': len(requeued_battles),
            'requeued_battles': requeued_battles,
            'original_error_count': error_count,
            'original_pending_count': pending_count_db,
            'queue_status': updated_queue_status
        })

    except Exception as e:
        logger.error(f"自动重新加入战斗时出错: {e}")
        return JsonResponse({
            'success': False,
            'error': f'自动重新加入战斗失败: {str(e)}'
        }, status=500)
